diff --git a/ark_guard/abckit_wrapper/BUILD.gn b/ark_guard/abckit_wrapper/BUILD.gn index 7b1b326fde89821e1b9c4b738ba19dfa24d55ff8..6d823db69e55babe63d66917a9caee63d2810b78 100755 --- a/ark_guard/abckit_wrapper/BUILD.gn +++ b/ark_guard/abckit_wrapper/BUILD.gn @@ -18,17 +18,28 @@ config("abckit_wrapper_public_config") { } abckit_wrapper_sources = [ + "library/annotation.cpp", + "library/annotation_interface.cpp", + "library/annotation_linker.cpp", + "library/annotation_target_visitor.cpp", "library/base_module.cpp", "library/child_visitor.cpp", "library/class.cpp", "library/class_hierarchy_builder.cpp", "library/class_visitor.cpp", + "library/field.cpp", "library/file_view.cpp", + "library/hierarchy_dumper.cpp", + "library/member.cpp", + "library/member_visitor.cpp", + "library/method.cpp", + "library/modifiers.cpp", "library/module.cpp", "library/module_visitor.cpp", "library/namespace.cpp", "library/object.cpp", "library/object_visitor.cpp", + "library/string_util.cpp", ] ohos_static_library("abckit_wrapper_static") { diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/annotation.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/annotation.h new file mode 100644 index 0000000000000000000000000000000000000000..2e09b43c5abbe641cc78758ee1dabf2e74948d69 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/annotation.h @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_ANNOTATION_H +#define ABCKIT_WRAPPER_ANNOTATION_H + +#include "libabckit/cpp/abckit_cpp.h" +#include "object.h" +#include "visitor.h" + +namespace abckit_wrapper { + +/** + * @brief Annotation + */ +class Annotation final : public Object, public SingleImplObject { +public: + /** + * @brief Annotation Constructor + * @param annotation abckit::core::Annotation + */ + explicit Annotation(abckit::core::Annotation annotation) : SingleImplObject(std::move(annotation)) {} + + std::string GetName() const override; + + /** + * @brief Tells if Annotation is defined in the same binary or externally in another binary. + * @return Returns `true` if Annotation is defined in another binary and `false` if defined locally. + */ + bool IsExternal() const; + + /** + * @brief Accept AnnotationVisitor visit + * @param visitor AnnotationVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool Accept(AnnotationVisitor &visitor); + + /** + * Annotation referenced AnnotationInterface + */ + std::optional ai_; + /** + * Annotation's owner object + */ + std::optional owner_; +}; + +/** + * @brief AnnotationTarget + * which object can be added annotation + */ +class AnnotationTarget { +public: + /** + * @brief AnnotationTarget default Destructor + */ + virtual ~AnnotationTarget() = default; + + /** + * @brief Annotations accept visit + * @param visitor AnnotationVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool AnnotationsAccept(AnnotationVisitor &visitor); + + /** + * @brief Get annotation name array + * @return annotation name array + */ + std::vector GetAnnotationNames() const; + +protected: + /** + * @brief Init annotations with abckit::core::Annotation vector + * @return AbckitWrapperErrorCode + */ + AbckitWrapperErrorCode InitAnnotations(); + + /** + * @brief Init for each annotation + * @param annotation Annotation + */ + virtual void InitAnnotation(Annotation *annotation) = 0; + + /** + * @brief Get abckit::core::Annotation from annotation target impl + * @return annotations + */ + virtual std::vector GetAnnotations() const = 0; + + /** + * Annotation target annotation + */ + std::unordered_map> annotations_; +}; + +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_ANNOTATION_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/annotation_interface.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/annotation_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..909df13cf7656e1fe2b6b5f7eac1602cb1aa6c40 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/annotation_interface.h @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_ANNOTATION_INTERFACE_H +#define ABCKIT_WRAPPER_ANNOTATION_INTERFACE_H + +#include "libabckit/cpp/abckit_cpp.h" +#include "object.h" +#include "visitor.h" + +namespace abckit_wrapper { +/** + * @brief AnnotationInterface + */ +class AnnotationInterface final : public Object, public SingleImplObject { +public: + /** + * @brief AnnotationInterface Constructor + * @param ai abckit::core::AnnotationInterface + */ + explicit AnnotationInterface(abckit::core::AnnotationInterface ai) : SingleImplObject(std::move(ai)) {} + + std::string GetName() const override; + + /** + * @brief Accept visit + * @param visitor AnnotationInterfaceVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool Accept(AnnotationInterfaceVisitor &visitor); + + /** + * @brief Accept ChildVisitor visit + * @param visitor ChildVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool Accept(ChildVisitor &visitor); +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_ANNOTATION_INTERFACE_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/base_module.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/base_module.h index a63a2afa39a310f70c497c815b5f1516101ae572..69531bfe4e14cd1f38f25fdc6c650b1f4f922229 100644 --- a/ark_guard/abckit_wrapper/include/abckit_wrapper/base_module.h +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/base_module.h @@ -55,11 +55,17 @@ protected: private: AbckitWrapperErrorCode InitNamespaces(); + AbckitWrapperErrorCode InitFunctions(); + + AbckitWrapperErrorCode InitModuleFields(); + AbckitWrapperErrorCode InitClasses(); AbckitWrapperErrorCode InitInterfaces(); AbckitWrapperErrorCode InitEnums(); + + AbckitWrapperErrorCode InitAnnotationInterfaces(); }; } // namespace abckit_wrapper diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/class.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/class.h index 248a455bb5c1f1a9eb8b8dd7d2daaa0275d89b1b..8bdfbdf5aa3da65ea718dfb6cd1fe1f84731309c 100644 --- a/ark_guard/abckit_wrapper/include/abckit_wrapper/class.h +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/class.h @@ -16,16 +16,15 @@ #ifndef ABCKIT_WRAPPER_CLASS_H #define ABCKIT_WRAPPER_CLASS_H -#include "libabckit/cpp/abckit_cpp.h" -#include "visitor.h" -#include "modifiers.h" -#include "object.h" +#include "method.h" +#include "field.h" namespace abckit_wrapper { /** * @brief Class */ class Class final : public Object, + public AnnotationTarget, public AccessFlagsTarget, public MultiImplObject { public: @@ -48,6 +47,24 @@ public: */ bool IsExternal() const; + /** + * @brief Check if it is an interface + * @return Returns `true` Class actual is interface, `false` not interface + */ + bool IsInterface() const; + + /** + * @brief Check if it is a class + * @return Returns `true` Class actual is class, `false` not class + */ + bool IsClass() const; + + /** + * @brief Check if it is an enum + * @return Returns `true` Class actual is enum, `false` not enum + */ + bool IsEnum() const; + /** * @brief Accept visit * @param visitor ClassVisitor @@ -62,6 +79,13 @@ public: */ bool Accept(ChildVisitor &visitor); + /** + * @brief Class members accept visit + * @param visitor MemberVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool MembersAccept(MemberVisitor &visitor); + /** * @brief Class hierarchy accept * @param visitor ClassVisitor @@ -75,12 +99,22 @@ public: bool visitSubclasses); private: + AbckitWrapperErrorCode InitMethods(); + + AbckitWrapperErrorCode InitFields(); + + void InitAnnotation(Annotation *annotation) override; + + std::vector GetAnnotations() const override; + void InitAccessFlags() override; public: std::optional superClass_; std::unordered_map interfaces_; std::unordered_map subClasses_; + std::unordered_map methodTable_; + std::unordered_map fieldTable_; }; } // namespace abckit_wrapper diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/field.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/field.h new file mode 100644 index 0000000000000000000000000000000000000000..6fb87795bdd76d991f01cf5a5b1cf34aeaddf1f2 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/field.h @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_FIELD_H +#define ABCKIT_WRAPPER_FIELD_H + +#include +#include "libabckit/cpp/abckit_cpp.h" +#include "member.h" +#include "visitor.h" + +namespace abckit_wrapper { +/** + * @brief Field + */ +class Field final + : public Member, + public MultiImplObject { +public: + /** + * Field Constructor + * @param field build from abckit::core field + * abckit::core::ModuleField + * abckit::core::NamespaceField + * abckit::core::ClassField + * abckit::core::InterfaceField + * abckit::core::EnumField + */ + explicit Field(std::variant + field) + : MultiImplObject(std::move(field)) + { + } + + AbckitWrapperErrorCode Init() override; + + std::string GetName() const override; + + /** + * @brief Get field type name + * @return std::string field type name + */ + std::string GetType() const; + + /** + * @brief Check if field is interface field + * @return true if field is interface field + */ + bool IsInterfaceField() const; + + /** + * @brief Accept visit + * @param visitor FieldVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool Accept(FieldVisitor &visitor); + + /** + * @brief Accept ChildVisitor visit + * @param visitor ChildVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool Accept(ChildVisitor &visitor); + +private: + AbckitWrapperErrorCode InitSignature() override; + + void InitAccessFlags() override; + + void InitAnnotation(Annotation *annotation) override; + + std::vector GetAnnotations() const override; +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_FIELD_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/hierarchy_dumper.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/hierarchy_dumper.h new file mode 100644 index 0000000000000000000000000000000000000000..f96d885b581df3074a1f889f9fb2bc7edb41f161 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/hierarchy_dumper.h @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_HIERARCHY_DUMPER_H +#define ABCKIT_WRAPPER_HIERARCHY_DUMPER_H + +#include +#include "file_view.h" + +namespace abckit_wrapper { + +/** + * @brief HierarchyDumper + * dump fileView hierarchy + */ +class HierarchyDumper final : public ModuleVisitor, public ChildVisitor, public AnnotationVisitor { +public: + /** + * @brief HierarchyDumper Constructor + * @param fileView abc fileView + * @param path dump file path + */ + explicit HierarchyDumper(FileView &fileView, const std::string_view &path) + : fileView_(fileView), ofstream_(path.data()) + { + } + + /** + * Dump fileView hierarchy to file + * @return AbckitWrapperErrorCode + */ + AbckitWrapperErrorCode Dump(); + +private: + static std::string GetIndent(Object *object); + + bool Visit(Module *module) override; + + bool VisitNamespace(Namespace *ns) override; + + bool VisitMethod(Method *method) override; + + bool VisitField(Field *field) override; + + bool VisitClass(Class *clazz) override; + + bool Visit(Annotation *annotation) override; + + FileView &fileView_; + std::ofstream ofstream_; +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_HIERARCHY_DUMPER_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/member.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/member.h new file mode 100644 index 0000000000000000000000000000000000000000..736b4cf289d3620862e2e8f36d00d7dbd2957ea9 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/member.h @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_MEMBER_H +#define ABCKIT_WRAPPER_MEMBER_H + +#include "object.h" +#include "annotation.h" +#include "modifiers.h" + +namespace abckit_wrapper { + +/** + * @brief Member + * Class method or field + */ +class Member : public Object, public AnnotationTarget, public AccessFlagsTarget { +public: + /** + * @brief Get member descriptor + * 1. normal method: (param1Type, param2Type, ..., paramNType):returnType + * 2. setter&getter method: field(fieldType) -> field; ()fieldType -> field + * 3. field: "" + * @return member descriptor + */ + [[nodiscard]] std::string GetDescriptor(); + + /** + * @brief Get member raw name + * 1. normal method: methodName + * 2. setter&getter method: field(fieldType) -> field; ()fieldType -> field + * 3. field: fieldName (ignore ) + * @return member raw name + */ + [[nodiscard]] std::string GetRawName(); + + /** + * @brief Get member signature + * @return member rawName + descriptor + */ + [[nodiscard]] std::string GetSignature(); + + /** + * @brief Member accept visit + * @param visitor MemberVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool MemberAccept(MemberVisitor &visitor); + +protected: + /** + * @brief Init member's signature, signature contains rawName and descriptor + * @return `ERR_SUCCESS` for success otherwise for false + */ + virtual AbckitWrapperErrorCode InitSignature() = 0; + +private: + /** + * @brief Refresh signature (if cachedName changed) + * @return `ERR_SUCCESS` for success otherwise for false + */ + AbckitWrapperErrorCode RefreshSignature(); + +public: + /** + * Member raw name + */ + std::string rawName_; + + /** + * Member descriptor + */ + std::string descriptor_; + +protected: + /** + * Member cached name, if member cached name changed, rawName and descriptor should be refreshed + */ + std::string cachedName_; +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_MEMBER_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/method.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/method.h new file mode 100644 index 0000000000000000000000000000000000000000..f0f4f6c2c9564dc1706f6ddc4b2837176e43ece9 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/method.h @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_METHOD_H +#define ABCKIT_WRAPPER_METHOD_H + +#include "libabckit/cpp/abckit_cpp.h" +#include "member.h" +#include "visitor.h" + +namespace abckit_wrapper { + +/** + * @brief Parameter + */ +class Parameter final : public Object, public SingleImplObject { +public: + /** + * @brief Parameter Constructor + * @param param abckit::core::FunctionParam + */ + explicit Parameter(abckit::core::FunctionParam param) : SingleImplObject(std::move(param)) {} + + std::string GetName() const override; + + /** + * @brief Get parameter type name + * @return parameter type name + */ + [[nodiscard]] std::string GetTypeName() const; + + /** + * @brief Accept visit + * @param visitor ParameterVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool Accept(ParameterVisitor &visitor); + + /** + * parameter owing method + */ + std::optional owingMethod_; +}; + +/** + * @brief Method + * + * function(owing to module) or method(owing to class) + */ +class Method final : public Member, public SingleImplObject { +public: + /** + * @brief Method Constructor + * @param function abckit::core::Function + */ + explicit Method(abckit::core::Function function) : SingleImplObject(std::move(function)) {} + + AbckitWrapperErrorCode Init() override; + + std::string GetName() const override; + + /** + * @brief Tells if Method is constructor + * @return `true` if Method is constructor + */ + bool IsConstructor() const; + + /** + * @brief Accept visit + * @param visitor MethodVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool Accept(MethodVisitor &visitor); + + /** + * @brief Children accept visit + * @param visitor ChildVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool Accept(ChildVisitor &visitor); + + /** + * @brief Parameters accept visit + * @param visitor ParameterVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool ParametersAccept(ParameterVisitor &visitor) const; + +private: + AbckitWrapperErrorCode InitSignature() override; + + void InitAccessFlags() override; + + void InitAnnotation(Annotation *annotation) override; + + std::vector GetAnnotations() const override; + + AbckitWrapperErrorCode InitParameters(); + + std::vector> parameters_; +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_METHOD_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/module.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/module.h index 9037467c4ea7179fb5e7650728fae2196ac673ff..8b096f1176edf1d3f8af29de5e2b5875a8cd0414 100644 --- a/ark_guard/abckit_wrapper/include/abckit_wrapper/module.h +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/module.h @@ -17,6 +17,7 @@ #define ABCKIT_WRAPPER_MODULE_H #include "base_module.h" +#include "annotation_interface.h" #include "namespace.h" #include "class.h" #include "visitor.h" @@ -85,6 +86,20 @@ public: */ bool NamespacesAccept(NamespaceVisitor &visitor); + /** + * @brief Module methods(functions & methods) accept visit + * @param visitor MethodVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool MethodsAccept(MethodVisitor &visitor); + + /** + * @brief Module fields accept visit + * @param visitor FieldVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool FieldsAccept(FieldVisitor &visitor); + /** * @brief Module classes accept visit * @param visitor ClassVisitor @@ -92,6 +107,20 @@ public: */ bool ClassesAccept(ClassVisitor &visitor); + /** + * @brief Module annotationInterfaces accept visit + * @param visitor AnnotationInterfaceVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool AnnotationInterfacesAccept(AnnotationInterfaceVisitor &visitor); + + /** + * @brief Module annotations accept visit + * @param visitor AnnotationVisitor + * @return `false` if was early exited. Otherwise - `true`. + */ + bool AnnotationsAccept(AnnotationVisitor &visitor); + private: template bool TypedObjectsAccept(T &visitor); diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/object.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/object.h index 8a9feaffe6ac59f30bba27e4bf1e619a1b2031ec..b31751c9e77fe475cb47ecf3ad7820ee5a95817f 100644 --- a/ark_guard/abckit_wrapper/include/abckit_wrapper/object.h +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/object.h @@ -29,9 +29,12 @@ namespace abckit_wrapper { class Module; class Namespace; +class Method; +class Field; class Class; +class AnnotationInterface; -using Child = std::variant; +using Child = std::variant; /** * @brief Object @@ -132,18 +135,6 @@ public: return this->impl_.GetName(); } - /** - * @brief Set object raw name - * @tparam ArkTsType arkts impl type - * @param name name to set - * @return `true` for success - */ - template - [[nodiscard]] bool SetObjectName(const std::string &name) const - { - return GetArkTsImpl().SetName(name); - } - /** * abckit::core object impl */ diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor.h index 1c324be3ccca7f68e43658ed5545ead607ecb841..c43f6bb78566dacc52863ecd01a7886fdbd8d1cb 100644 --- a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor.h +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor.h @@ -18,7 +18,11 @@ #include "visitor/module_visitor.h" #include "visitor/namespace_visitor.h" +#include "visitor/member_visitor.h" +#include "visitor/method_visitor.h" +#include "visitor/field_visitor.h" #include "visitor/class_visitor.h" +#include "visitor/annotation_visitor.h" #include "visitor/child_visitor.h" #endif // ABCKIT_WRAPPER_VISITOR_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/annotation_visitor.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/annotation_visitor.h new file mode 100644 index 0000000000000000000000000000000000000000..4c29a7fe67eeb8de259123df9bdd7995eea5e9b2 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/annotation_visitor.h @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_ANNOTATION_INTERFACE_VISITOR_H +#define ABCKIT_WRAPPER_ANNOTATION_INTERFACE_VISITOR_H + +#include "visitor_wrapper.h" + +namespace abckit_wrapper { + +class AnnotationInterface; +class Annotation; + +/** + * @brief AnnotationInterfaceVisitor + */ +class AnnotationInterfaceVisitor { +public: + /** + * @brief AnnotationInterfaceVisitor default Destructor + */ + virtual ~AnnotationInterfaceVisitor() = default; + + /** + * @brief Visit annotationInterface + * @param ai visited annotationInterface + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool Visit(AnnotationInterface *ai) = 0; +}; + +/** + * @brief AnnotationVisitor + */ +class AnnotationVisitor : public WrappedVisitor { +public: + /** + * @brief Visit annotation + * @param annotation visited annotation + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool Visit(Annotation *annotation) = 0; +}; + +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_ANNOTATION_INTERFACE_VISITOR_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/child_visitor.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/child_visitor.h index b6ebf0d23c5c2f6bd85da1bcafbf7013d9147019..8e131d3f3734d0801a45e94efb34aaedbd4c7fb6 100644 --- a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/child_visitor.h +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/child_visitor.h @@ -19,7 +19,10 @@ namespace abckit_wrapper { class Namespace; +class Method; +class Field; class Class; +class AnnotationInterface; /** * @brief ChildVisitor @@ -38,13 +41,34 @@ public: */ virtual bool VisitNamespace(Namespace *ns); + /** + * @brief Visit method + * @param method visited method + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool VisitMethod(Method *method); + + /** + * @brief Visit field + * @param field visited field + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool VisitField(Field *field); + /** * @brief Visit class * @param clazz visited class * @return `false` if was early exited. Otherwise - `true`. */ virtual bool VisitClass(Class *clazz); + + /** + * @brief Visit annotationInterface + * @param ai visited annotationInterface + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool VisitAnnotationInterface(AnnotationInterface *ai); }; } // namespace abckit_wrapper -#endif // ABCKIT_WRAPPER_CHILD_VISITOR_H \ No newline at end of file +#endif // ABCKIT_WRAPPER_CHILD_VISITOR_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/class_visitor.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/class_visitor.h index f175bdb3f43d86ee72cfbe8c45200b2da5cd0663..5c38f76ecf0355f24828fc30e0edea957083ec89 100644 --- a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/class_visitor.h +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/class_visitor.h @@ -17,6 +17,7 @@ #define ABCKIT_WRAPPER_CLASS_VISITOR_H #include "visitor_wrapper.h" +#include "member_visitor.h" namespace abckit_wrapper { @@ -74,6 +75,21 @@ private: bool Accepted(Class *clazz) override; }; +/** + * @brief ClassMemberVisitor + */ +class ClassMemberVisitor final : public ClassVisitor, public BaseVisitorWrapper { +public: + /** + * @brief ClassMemberVisitor Constructor + * @param visitor MemberVisitor + */ + explicit ClassMemberVisitor(MemberVisitor &visitor) : BaseVisitorWrapper(visitor) {} + +private: + bool Visit(Class *clazz) override; +}; + } // namespace abckit_wrapper #endif // ABCKIT_WRAPPER_CLASS_VISITOR_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/field_visitor.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/field_visitor.h new file mode 100644 index 0000000000000000000000000000000000000000..0cce291bd136bb1ed87ea5bd020dc64f2d75b503 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/field_visitor.h @@ -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. + */ + +#ifndef ABCKIT_WRAPPER_FIELD_VISITOR_H +#define ABCKIT_WRAPPER_FIELD_VISITOR_H + +namespace abckit_wrapper { + +class Field; + +/** + * @brief FieldVisitor + */ +class FieldVisitor { +public: + /** + * @brief FieldVisitor default Destructor + */ + virtual ~FieldVisitor() = default; + + /** + * @brief Visit field + * @param field visited field + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool Visit(Field *field) = 0; +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_FIELD_VISITOR_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/member_visitor.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/member_visitor.h new file mode 100644 index 0000000000000000000000000000000000000000..f7374d2e7cf23602e31d8a63eba5e1de36f7ef09 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/member_visitor.h @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_MEMBER_VISITOR_H +#define ABCKIT_WRAPPER_MEMBER_VISITOR_H + +#include "visitor_wrapper.h" + +namespace abckit_wrapper { + +class Member; + +/** + * @brief MemberVisitor + */ +class MemberVisitor : public WrappedVisitor { +public: + /** + * @brief Visit member + * @param member visited member + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool Visit(Member *member) = 0; +}; + +/** + * @brief MemberFilter + * filter the accepted member for visit + */ +class MemberFilter : public MemberVisitor, public BaseVisitorWrapper { +public: + /** + * @brief MemberFilter Constructor + * @param visitor MemberVisitor + */ + explicit MemberFilter(MemberVisitor &visitor) : BaseVisitorWrapper(visitor) {} + + /** + * @brief Given member whether accepted + * @param member visited member + * @return `true`: member will be visit `false`: member will be skipped + */ + virtual bool Accepted(Member *member) = 0; + +private: + bool Visit(Member *member) override; +}; + +/** + * @brief MemberAccessFlagFilter + * filter the member by accessFlags + * 1. (rejectFlags & member.accessFlags) != 0 skipped + * 2. (acceptFlags & member.accessFlags) != 0 accepted + */ +class MemberAccessFlagFilter final : public MemberFilter { +public: + /** + * MemberAccessFlagFilter + * @param visitor MemberVisitor + * @param acceptFlags accept accessFlags + * @param rejectFlags reject accessFlags + */ + MemberAccessFlagFilter(MemberVisitor &visitor, const uint32_t acceptFlags, const uint32_t rejectFlags = 0) + : MemberFilter(visitor), accessFlags_(acceptFlags), rejectFlags_(rejectFlags) + { + } + +private: + bool Accepted(Member *member) override; + + /** + * accept accessFlags + */ + uint32_t accessFlags_; + + /** + * reject accessFlags + */ + uint32_t rejectFlags_; +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_MEMBER_VISITOR_H \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/method_visitor.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/method_visitor.h new file mode 100644 index 0000000000000000000000000000000000000000..54eacc27cfc1898867ff6ec056e442f4212d0d17 --- /dev/null +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/method_visitor.h @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_METHOD_VISITOR_H +#define ABCKIT_WRAPPER_METHOD_VISITOR_H + +namespace abckit_wrapper { + +class Method; +class Parameter; + +/** + * @brief MethodVisitor + */ +class MethodVisitor { +public: + /** + * @brief MethodVisitor default Destructor + */ + virtual ~MethodVisitor() = default; + + /** + * @brief Visit method + * @param method visited method + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool Visit(Method *method) = 0; +}; + +/** + * @brief ParameterVisitor + */ +class ParameterVisitor { +public: + /** + * @brief ParameterVisitor default Destructor + */ + virtual ~ParameterVisitor() = default; + + /** + * @brief Visit method parameter + * @param parameter visited parameter + * @return `false` if was early exited. Otherwise - `true`. + */ + virtual bool Visit(Parameter *parameter) = 0; +}; + +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_METHOD_VISITOR_H diff --git a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/module_visitor.h b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/module_visitor.h index d293d4f6aebb37cf55d17bf083d8a6572c2d6691..8fd2e85b18b3c752e4435337036f3732ebb2238a 100644 --- a/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/module_visitor.h +++ b/ark_guard/abckit_wrapper/include/abckit_wrapper/visitor/module_visitor.h @@ -18,6 +18,7 @@ #include "visitor_wrapper.h" #include "class_visitor.h" +#include "annotation_visitor.h" namespace abckit_wrapper { @@ -91,6 +92,22 @@ private: bool Visit(Module *module) override; }; +/** + * @brief ModuleAnnotationVisitor + * visit all module annotations + */ +class ModuleAnnotationVisitor final : public ModuleVisitor, public BaseVisitorWrapper { +public: + /** + * @brief ModuleAnnotationsVisitor Constructor + * @param visitor AnnotationVisitor + */ + explicit ModuleAnnotationVisitor(AnnotationVisitor &visitor) : BaseVisitorWrapper(visitor) {} + +private: + bool Visit(Module *module) override; +}; + } // namespace abckit_wrapper #endif // ABCKIT_WRAPPER_MODULE_VISITOR_H diff --git a/ark_guard/abckit_wrapper/library/annotation.cpp b/ark_guard/abckit_wrapper/library/annotation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2af619483553c101dd5c7d77b9526f2a78645b4b --- /dev/null +++ b/ark_guard/abckit_wrapper/library/annotation.cpp @@ -0,0 +1,70 @@ +/** + * 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 "abckit_wrapper/annotation.h" +#include "logger.h" + +std::string abckit_wrapper::Annotation::GetName() const +{ + return this->GetObjectName(); +} + +bool abckit_wrapper::Annotation::IsExternal() const +{ + return this->impl_.IsExternal(); +} + +bool abckit_wrapper::Annotation::Accept(AnnotationVisitor &visitor) +{ + return visitor.Visit(this); +} + +AbckitWrapperErrorCode abckit_wrapper::AnnotationTarget::InitAnnotations() +{ + for (const auto &coreAnnotation : this->GetAnnotations()) { + auto annotation = std::make_unique(coreAnnotation); + // init annotation's owner + this->InitAnnotation(annotation.get()); + const auto rc = annotation->Init(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init Annotation:" << coreAnnotation.GetName() << rc; + return rc; + } + LOG_I << "Found Annotation:" << annotation->GetFullyQualifiedName(); + this->annotations_.emplace(annotation->GetFullyQualifiedName(), std::move(annotation)); + } + + return ERR_SUCCESS; +} + +bool abckit_wrapper::AnnotationTarget::AnnotationsAccept(AnnotationVisitor &visitor) +{ + for (const auto &[_, annotation] : this->annotations_) { + if (!annotation->Accept(visitor)) { + return false; + } + } + + return true; +} + +std::vector abckit_wrapper::AnnotationTarget::GetAnnotationNames() const +{ + std::vector annotationNames; + annotationNames.reserve(this->annotations_.size()); + for (const auto &[_, annotation] : this->annotations_) { + annotationNames.emplace_back(annotation->GetName()); + } + return annotationNames; +} diff --git a/ark_guard/abckit_wrapper/library/annotation_interface.cpp b/ark_guard/abckit_wrapper/library/annotation_interface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ea8dc74487156ef60885597dff122ccddc37fc1 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/annotation_interface.cpp @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "abckit_wrapper/annotation_interface.h" + +std::string abckit_wrapper::AnnotationInterface::GetName() const +{ + return this->GetObjectName(); +} + +bool abckit_wrapper::AnnotationInterface::Accept(AnnotationInterfaceVisitor &visitor) +{ + return visitor.Visit(this); +} + +bool abckit_wrapper::AnnotationInterface::Accept(ChildVisitor &visitor) +{ + return visitor.VisitAnnotationInterface(this); +} diff --git a/ark_guard/abckit_wrapper/library/annotation_linker.cpp b/ark_guard/abckit_wrapper/library/annotation_linker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25a10407f70bdd592d318670b8fc501e7b858af2 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/annotation_linker.cpp @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "annotation_linker.h" +#include "full_name_util.h" +#include "logger.h" + +AbckitWrapperErrorCode abckit_wrapper::AnnotationLinker::Link() +{ + this->fileView_.ModulesAccept(this->Wrap().Wrap()); + return this->result; +} + +bool abckit_wrapper::AnnotationLinker::Visit(Annotation *annotation) +{ + if (annotation->IsExternal()) { + return true; + } + + const auto fullName = FullNameUtil::GetFullName(annotation->impl_.GetInterface()); + const auto ai = this->fileView_.Get(fullName); + if (!ai.has_value()) { + this->result = ERR_INNER_ERROR; + LOG_E << "Failed to get annotation interface:" << fullName; + return false; + } + LOG_I << "Link annotation " << annotation->GetName() << " to " << fullName; + annotation->ai_ = ai; + + return true; +} diff --git a/ark_guard/abckit_wrapper/library/annotation_linker.h b/ark_guard/abckit_wrapper/library/annotation_linker.h new file mode 100644 index 0000000000000000000000000000000000000000..52c3afc98438a7223f9087abc7674f4a2f207ed6 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/annotation_linker.h @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_ANNOTATION_LINKER_H +#define ABCKIT_WRAPPER_ANNOTATION_LINKER_H + +#include "abckit_wrapper/file_view.h" + +namespace abckit_wrapper { + +/** + * @brief AnnotationLinker + * link all annotation's AnnotationInterface + */ +class AnnotationLinker final : public AnnotationVisitor { +public: + /** + * @brief AnnotationLinker Constructor + * @param fileView fileView + */ + explicit AnnotationLinker(FileView &fileView) : fileView_(fileView) {} + + /** + * @brief Link all annotation's AnnotationInterface + * @return AbckitWrapperErrorCode + */ + AbckitWrapperErrorCode Link(); + +private: + bool Visit(Annotation *annotation) override; + + FileView &fileView_; + AbckitWrapperErrorCode result = ERR_SUCCESS; +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_ANNOTATION_LINKER_H diff --git a/ark_guard/abckit_wrapper/library/annotation_target_visitor.cpp b/ark_guard/abckit_wrapper/library/annotation_target_visitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb0ec5c9edb2bf270e2d799ba35d5acbd83b6ca3 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/annotation_target_visitor.cpp @@ -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. + */ + +#include "annotation_target_visitor.h" +#include "abckit_wrapper/class.h" + +bool abckit_wrapper::AnnotationTargetVisitor::operator()(Namespace *) const +{ + return true; +} + +bool abckit_wrapper::AnnotationTargetVisitor::operator()(Method *method) const +{ + return method->AnnotationsAccept(this->visitor_); +} + +bool abckit_wrapper::AnnotationTargetVisitor::operator()(Field *field) const +{ + return field->AnnotationsAccept(this->visitor_); +} + +bool abckit_wrapper::AnnotationTargetVisitor::operator()(Class *clazz) const +{ + return clazz->AnnotationsAccept(this->visitor_); +} + +bool abckit_wrapper::AnnotationTargetVisitor::operator()(AnnotationInterface *ai) const +{ + return true; +} diff --git a/ark_guard/abckit_wrapper/library/annotation_target_visitor.h b/ark_guard/abckit_wrapper/library/annotation_target_visitor.h new file mode 100644 index 0000000000000000000000000000000000000000..ba2e477279ee97c5e704ad6d62b70a1040774bdc --- /dev/null +++ b/ark_guard/abckit_wrapper/library/annotation_target_visitor.h @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_ANNOTATION_TARGET_VISITOR_H +#define ABCKIT_WRAPPER_ANNOTATION_TARGET_VISITOR_H + +#include "abckit_wrapper/annotation.h" +#include "abckit_wrapper/visitor/annotation_visitor.h" + +namespace abckit_wrapper { +/** + * @brief AnnotationTargetVisitor + */ +class AnnotationTargetVisitor { +public: + /** + * @brief AnnotationTargetVisitor Constructor + * @param visitor AnnotationVisitor + */ + explicit AnnotationTargetVisitor(AnnotationVisitor &visitor) : visitor_(visitor) {} + + /** + * @brief Visit annotation target for Namespace (ignored) + * @param ns visited Namespace + * @return `false` if was early exited. Otherwise - `true`. + */ + bool operator()(Namespace *ns) const; + + /** + * @brief Visit annotation target for Method + * @param method visited Method + * @return `false` if was early exited. Otherwise - `true`. + */ + bool operator()(Method *method) const; + + /** + * @brief Visit annotation target for Field + * @param field visited Field + * @return `false` if was early exited. Otherwise - `true`. + */ + bool operator()(Field *field) const; + + /** + * @brief Visit annotation target for Class + * @param clazz visited Class + * @return `false` if was early exited. Otherwise - `true`. + */ + bool operator()(Class *clazz) const; + + /** + * @brief Visit annotation target for AnnotationInterface (ignored) + * @param ai visited AnnotationInterface + * @return `false` if was early exited. Otherwise - `true`. + */ + bool operator()(AnnotationInterface *ai) const; + +private: + AnnotationVisitor &visitor_; +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_ANNOTATION_TARGET_VISITOR_H diff --git a/ark_guard/abckit_wrapper/library/base_module.cpp b/ark_guard/abckit_wrapper/library/base_module.cpp index 820777512bed85917cc0104cd08a7a91b79e0331..a7253482dd72867838379e64f77c2df6f29c6c26 100644 --- a/ark_guard/abckit_wrapper/library/base_module.cpp +++ b/ark_guard/abckit_wrapper/library/base_module.cpp @@ -26,6 +26,18 @@ AbckitWrapperErrorCode abckit_wrapper::BaseModule::Init() return rc; } + rc = this->InitFunctions(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init Functions:" << rc; + return rc; + } + + rc = this->InitModuleFields(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init ModuleFields:" << rc; + return rc; + } + rc = this->InitClasses(); if (ABCKIT_WRAPPER_ERROR(rc)) { LOG_E << "Failed to init Classes:" << rc; @@ -44,6 +56,12 @@ AbckitWrapperErrorCode abckit_wrapper::BaseModule::Init() return rc; } + rc = this->InitAnnotationInterfaces(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init AnnotationInterfaces:" << rc; + return rc; + } + return ERR_SUCCESS; } @@ -69,6 +87,50 @@ AbckitWrapperErrorCode abckit_wrapper::BaseModule::InitNamespaces() this->impl_); } +AbckitWrapperErrorCode abckit_wrapper::BaseModule::InitFunctions() +{ + return std::visit( + [&](const auto &object) { + for (auto &function : object.GetTopLevelFunctions()) { + auto method = std::make_unique(function); + this->InitForObject(method.get()); + LOG_I << "Found Function:" << method->GetFullyQualifiedName(); + auto rc = method->Init(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init Function:" << function.GetName() << " errCode:" << rc; + return rc; + } + this->children_.emplace(method->GetFullyQualifiedName(), method.get()); + method->owningModule_.value()->Add(std::move(method)); + } + + return ERR_SUCCESS; + }, + this->impl_); +} + +AbckitWrapperErrorCode abckit_wrapper::BaseModule::InitModuleFields() +{ + return std::visit( + [&](const auto &object) { + for (auto &coreField : object.GetFields()) { + auto field = std::make_unique(coreField); + this->InitForObject(field.get()); + LOG_I << "Found ModuleField:" << field->GetFullyQualifiedName(); + auto rc = field->Init(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init ModuleField:" << coreField.GetName() << " errCode:" << rc; + return rc; + } + this->children_.emplace(field->GetFullyQualifiedName(), field.get()); + field->owningModule_.value()->Add(std::move(field)); + } + + return ERR_SUCCESS; + }, + this->impl_); +} + AbckitWrapperErrorCode abckit_wrapper::BaseModule::InitClasses() { return std::visit( @@ -135,6 +197,29 @@ AbckitWrapperErrorCode abckit_wrapper::BaseModule::InitEnums() this->impl_); } +AbckitWrapperErrorCode abckit_wrapper::BaseModule::InitAnnotationInterfaces() +{ + return std::visit( + [&](const auto &object) { + for (auto &annotationInterface : object.GetAnnotationInterfaces()) { + auto ai = std::make_unique(annotationInterface); + this->InitForObject(ai.get()); + LOG_I << "Found AnnotationInterface:" << ai->GetFullyQualifiedName(); + auto rc = ai->Init(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init AnnotationInterface:" << annotationInterface.GetName() + << " errCode:" << rc; + return rc; + } + this->children_.emplace(ai->GetFullyQualifiedName(), ai.get()); + ai->owningModule_.value()->Add(std::move(ai)); + } + + return ERR_SUCCESS; + }, + this->impl_); +} + bool abckit_wrapper::BaseModule::IsExternal() { return std::visit([](const auto &object) { return object.IsExternal(); }, this->impl_); diff --git a/ark_guard/abckit_wrapper/library/child_visitor.cpp b/ark_guard/abckit_wrapper/library/child_visitor.cpp index 551d2b6ac1b2e0d42a8c427a68475018f565fcf2..22366e234240566d25ccf1f34506deb25594ec64 100644 --- a/ark_guard/abckit_wrapper/library/child_visitor.cpp +++ b/ark_guard/abckit_wrapper/library/child_visitor.cpp @@ -19,7 +19,22 @@ bool abckit_wrapper::ChildVisitor::VisitNamespace(Namespace *ns) return true; } +bool abckit_wrapper::ChildVisitor::VisitMethod(Method *method) +{ + return true; +} + +bool abckit_wrapper::ChildVisitor::VisitField(Field *field) +{ + return true; +} + bool abckit_wrapper::ChildVisitor::VisitClass(Class *clazz) { return true; -} \ No newline at end of file +} + +bool abckit_wrapper::ChildVisitor::VisitAnnotationInterface(AnnotationInterface *ai) +{ + return true; +} diff --git a/ark_guard/abckit_wrapper/library/class.cpp b/ark_guard/abckit_wrapper/library/class.cpp index acf81f929ba2d54699976c804e940e853d52ab04..9c10a45e8594e51056d9a961c8a9a43bef695051 100644 --- a/ark_guard/abckit_wrapper/library/class.cpp +++ b/ark_guard/abckit_wrapper/library/class.cpp @@ -20,6 +20,24 @@ AbckitWrapperErrorCode abckit_wrapper::Class::Init() { this->InitAccessFlags(); + auto rc = this->InitMethods(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init methods:" << rc; + return rc; + } + + rc = this->InitFields(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init fields:" << rc; + return rc; + } + + rc = this->InitAnnotations(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init annotations:" << rc; + return rc; + } + return ERR_SUCCESS; } @@ -28,6 +46,72 @@ std::string abckit_wrapper::Class::GetName() const return this->GetObjectName(); } +AbckitWrapperErrorCode abckit_wrapper::Class::InitMethods() +{ + return std::visit( + [&](const auto &object) { + for (auto &coreMethod : object.GetAllMethods()) { + auto method = std::make_unique(coreMethod); + method->owningModule_ = this->owningModule_; + method->parent_ = this; + LOG_I << "Found Method:" << method->GetFullyQualifiedName(); + auto rc = method->Init(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init method:" << coreMethod.GetName() << " errCode:" << rc; + return rc; + } + this->methodTable_.emplace(method->GetFullyQualifiedName(), method.get()); + this->children_.emplace(method->GetFullyQualifiedName(), method.get()); + method->owningModule_.value()->Add(std::move(method)); + } + + return ERR_SUCCESS; + }, + this->impl_); +} + +AbckitWrapperErrorCode abckit_wrapper::Class::InitFields() +{ + return std::visit( + [&](const auto &object) { + for (auto &coreField : object.GetFields()) { + auto field = std::make_unique(coreField); + field->owningModule_ = this->owningModule_; + field->parent_ = this; + LOG_I << "Found Field:" << field->GetFullyQualifiedName(); + auto rc = field->Init(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init field:" << coreField.GetName() << " errCode:" << rc; + return rc; + } + this->fieldTable_.emplace(field->GetFullyQualifiedName(), field.get()); + this->children_.emplace(field->GetFullyQualifiedName(), field.get()); + field->owningModule_.value()->Add(std::move(field)); + } + + return ERR_SUCCESS; + }, + this->impl_); +} + +void abckit_wrapper::Class::InitAnnotation(Annotation *annotation) +{ + annotation->owner_ = this; +} + +std::vector abckit_wrapper::Class::GetAnnotations() const +{ + if (const auto clazz = std::get_if(&this->impl_)) { + return clazz->GetAnnotations(); + } + + if (const auto interface = std::get_if(&this->impl_)) { + return interface->GetAnnotations(); + } + + return {}; +} + void abckit_wrapper::Class::InitAccessFlags() { if (const auto clazz = std::get_if(&this->impl_)) { @@ -41,11 +125,43 @@ bool abckit_wrapper::Class::IsExternal() const return std::visit([](const auto &object) { return object.IsExternal(); }, this->impl_); } +bool abckit_wrapper::Class::IsInterface() const +{ + return std::holds_alternative(this->impl_); +} + +bool abckit_wrapper::Class::IsClass() const +{ + return std::holds_alternative(this->impl_); +} + +bool abckit_wrapper::Class::IsEnum() const +{ + return std::holds_alternative(this->impl_); +} + bool abckit_wrapper::Class::Accept(ClassVisitor &visitor) { return visitor.Visit(this); } +bool abckit_wrapper::Class::MembersAccept(MemberVisitor &visitor) +{ + for (auto &[_, method] : this->methodTable_) { + if (!method->MemberAccept(visitor)) { + return false; + } + } + + for (auto &[_, field] : this->fieldTable_) { + if (!field->MemberAccept(visitor)) { + return false; + } + } + + return true; +} + bool abckit_wrapper::Class::Accept(ChildVisitor &visitor) { return visitor.VisitClass(this); diff --git a/ark_guard/abckit_wrapper/library/class_visitor.cpp b/ark_guard/abckit_wrapper/library/class_visitor.cpp index 4fafbd5933d9c5e152accb1b055b15615cc086e7..74043d364693b928296a4e7edaf9e71908ba256a 100644 --- a/ark_guard/abckit_wrapper/library/class_visitor.cpp +++ b/ark_guard/abckit_wrapper/library/class_visitor.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "abckit_wrapper/visitor/class_visitor.h" + #include "abckit_wrapper/class.h" bool abckit_wrapper::ClassFilter::Visit(Class *clazz) @@ -28,3 +29,8 @@ bool abckit_wrapper::LeafClassVisitor::Accepted(Class *clazz) { return clazz->subClasses_.empty(); } + +bool abckit_wrapper::ClassMemberVisitor::Visit(Class *clazz) +{ + return clazz->MembersAccept(this->visitor_); +} diff --git a/ark_guard/abckit_wrapper/library/field.cpp b/ark_guard/abckit_wrapper/library/field.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32d101d962d31fb57805757f97f5f74de5ca5a73 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/field.cpp @@ -0,0 +1,103 @@ +/** + * 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 "abckit_wrapper/field.h" + +#include +#include "logger.h" + +std::string abckit_wrapper::Field::GetName() const +{ + return this->GetObjectName(); +} + +std::string abckit_wrapper::Field::GetType() const +{ + return std::visit([&](const auto &fieldObj) { return fieldObj.GetType().GetName(); }, this->impl_); +} + +bool abckit_wrapper::Field::IsInterfaceField() const +{ + return std::holds_alternative(this->impl_); +} + +AbckitWrapperErrorCode abckit_wrapper::Field::Init() +{ + this->InitAccessFlags(); + + auto rc = this->InitSignature(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init field descriptor for:" << this->GetFullyQualifiedName(); + return rc; + } + + LOG_I << "signature:" << this->rawName_ + this->descriptor_; + + rc = this->InitAnnotations(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init field annotations:" << rc; + return rc; + } + + return ERR_SUCCESS; +} + +AbckitWrapperErrorCode abckit_wrapper::Field::InitSignature() +{ + const auto cachedName = this->GetName(); + this->rawName_ = std::regex_replace(cachedName, std::regex(""), ""); + this->descriptor_ = ""; + this->cachedName_ = cachedName; + return ERR_SUCCESS; +} + +void abckit_wrapper::Field::InitAccessFlags() +{ + if (const auto classField = std::get_if(&this->impl_)) { + this->accessFlags_ |= classField->IsPublic() ? AccessFlags::PUBLIC : AccessFlags::NONE; + this->accessFlags_ |= classField->IsProtected() ? AccessFlags::PROTECTED : AccessFlags::NONE; + this->accessFlags_ |= classField->IsPrivate() ? AccessFlags::PRIVATE : AccessFlags::NONE; + this->accessFlags_ |= classField->IsInternal() ? AccessFlags::INTERNAL : AccessFlags::NONE; + + this->accessFlags_ |= classField->IsStatic() ? AccessFlags::STATIC : AccessFlags::NONE; + } +} + +void abckit_wrapper::Field::InitAnnotation(Annotation *annotation) +{ + annotation->owner_ = this; +} + +std::vector abckit_wrapper::Field::GetAnnotations() const +{ + if (const auto classField = std::get_if(&this->impl_)) { + return classField->GetAnnotations(); + } + + if (const auto interfaceField = std::get_if(&this->impl_)) { + return interfaceField->GetAnnotations(); + } + + return {}; +} + +bool abckit_wrapper::Field::Accept(FieldVisitor &visitor) +{ + return visitor.Visit(this); +} + +bool abckit_wrapper::Field::Accept(ChildVisitor &visitor) +{ + return visitor.VisitField(this); +} diff --git a/ark_guard/abckit_wrapper/library/file_view.cpp b/ark_guard/abckit_wrapper/library/file_view.cpp index e895bbece7931ec48b6dfc5aa69ff448c2fa3a95..2301f45204ab2e2e132f3b200649e1b89a071f3d 100644 --- a/ark_guard/abckit_wrapper/library/file_view.cpp +++ b/ark_guard/abckit_wrapper/library/file_view.cpp @@ -14,6 +14,7 @@ */ #include "abckit_wrapper/file_view.h" #include "class_hierarchy_builder.h" +#include "annotation_linker.h" #include "logger.h" AbckitWrapperErrorCode abckit_wrapper::FileView::Init(const std::string_view &path) @@ -39,16 +40,24 @@ AbckitWrapperErrorCode abckit_wrapper::FileView::Init(const std::string_view &pa return rc; } + AnnotationLinker annotationLinker(*this); + rc = annotationLinker.Link(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to link annotation's interface:" << rc; + return rc; + } + return ERR_SUCCESS; } std::optional abckit_wrapper::FileView::GetModule(const std::string &moduleName) const { - if (this->moduleTable_.find(moduleName) == this->moduleTable_.end()) { + const auto it = this->moduleTable_.find(moduleName); + if (it == this->moduleTable_.end()) { return std::nullopt; } - return this->moduleTable_.at(moduleName); + return it->second; } std::optional abckit_wrapper::FileView::GetObject(const std::string &objectName) const diff --git a/ark_guard/abckit_wrapper/library/hierarchy_dumper.cpp b/ark_guard/abckit_wrapper/library/hierarchy_dumper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34c0a1e87a35676c80ef6e5a331da7584b1e099e --- /dev/null +++ b/ark_guard/abckit_wrapper/library/hierarchy_dumper.cpp @@ -0,0 +1,146 @@ +/** + * 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 "abckit_wrapper/hierarchy_dumper.h" +#include "logger.h" + +namespace { +constexpr std::string_view INDENT = " "; +} + +AbckitWrapperErrorCode abckit_wrapper::HierarchyDumper::Dump() +{ + if (!this->ofstream_.is_open()) { + LOG_E << "Failed to open dump file"; + return ERR_DUMP_ERROR; + } + + this->fileView_.ModulesAccept(*this); + + return ERR_SUCCESS; +} + +std::string abckit_wrapper::HierarchyDumper::GetIndent(Object *object) +{ + if (!object->data_.has_value()) { + LOG_W << "object data is empty for:" << object->GetFullyQualifiedName(); + return ""; + } + + if (const auto data = std::any_cast(&object->data_)) { + return *data; + } + + LOG_W << "object data is not a string for:" << object->GetFullyQualifiedName(); + return ""; +} + +bool abckit_wrapper::HierarchyDumper::Visit(Module *module) +{ + if (module->IsExternal()) { + return true; + } + + module->data_ = std::string(); // indent + ofstream_ << "Module:" << module->GetFullyQualifiedName() << std::endl; + + module->ChildrenAccept(*this); + + return true; +} + +bool abckit_wrapper::HierarchyDumper::VisitNamespace(Namespace *ns) +{ + const auto indent = GetIndent(ns->parent_.value()) + INDENT.data(); + ns->data_ = indent; + ofstream_ << indent << "Namespace:" << ns->GetName() << std::endl; + + ns->ChildrenAccept(*this); + + return true; +} + +bool abckit_wrapper::HierarchyDumper::VisitMethod(Method *method) +{ + const auto indent = GetIndent(method->parent_.value()) + INDENT.data(); + method->data_ = indent; + ofstream_ << indent << "Function:" << method->GetDescriptor() << std::endl; + + return true; +} + +bool abckit_wrapper::HierarchyDumper::VisitField(Field *field) +{ + const auto indent = GetIndent(field->parent_.value()) + INDENT.data(); + field->data_ = indent; + ofstream_ << indent << "ModuleField:" << field->GetName() << std::endl; + + return true; +} + +bool abckit_wrapper::HierarchyDumper::VisitClass(Class *clazz) +{ + const auto indent = GetIndent(clazz->parent_.value()) + INDENT.data(); + clazz->data_ = indent; + ofstream_ << indent << "Class:" << clazz->GetName() << std::endl; + + if (clazz->superClass_.has_value()) { + ofstream_ << indent << INDENT << "SuperClass:" << clazz->superClass_.value()->GetFullyQualifiedName() + << std::endl; + } + + if (!clazz->interfaces_.empty()) { + ofstream_ << indent << INDENT << "Interfaces:[ "; + for (const auto &[interfaceName, _] : clazz->interfaces_) { + ofstream_ << interfaceName << ", "; + } + ofstream_ << "]" << std::endl; + } + + if (!clazz->subClasses_.empty()) { + ofstream_ << indent << INDENT << "SubClasses:[ "; + for (const auto &[className, _] : clazz->subClasses_) { + ofstream_ << className << ", "; + } + ofstream_ << "]" << std::endl; + } + + clazz->AnnotationsAccept(*this); + + for (const auto &[_, method] : clazz->methodTable_) { + method->data_ = indent + INDENT.data(); + ofstream_ << indent << INDENT << "Method:" << method->GetDescriptor() << std::endl; + method->AnnotationsAccept(*this); + } + + for (const auto &[_, field] : clazz->fieldTable_) { + field->data_ = indent + INDENT.data(); + ofstream_ << indent << INDENT << "Field:" << field->GetDescriptor() << std::endl; + field->AnnotationsAccept(*this); + } + + return true; +} + +bool abckit_wrapper::HierarchyDumper::Visit(Annotation *annotation) +{ + if (annotation->IsExternal()) { + return true; + } + + const auto indent = GetIndent(annotation->owner_.value()) + INDENT.data(); + ofstream_ << indent << "Annotation:" << annotation->ai_.value()->GetFullyQualifiedName() << std::endl; + + return true; +} diff --git a/ark_guard/abckit_wrapper/library/member.cpp b/ark_guard/abckit_wrapper/library/member.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a09356e111567eac2a9171a3ab8a0c9f55cdc00 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/member.cpp @@ -0,0 +1,63 @@ +/** + * 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 "abckit_wrapper/member.h" +#include "logger.h" + +AbckitWrapperErrorCode abckit_wrapper::Member::RefreshSignature() +{ + if (this->cachedName_ == this->GetName()) { + return AbckitWrapperErrorCode::ERR_SUCCESS; + } + + const auto rc = this->InitSignature(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to refresh signature:" << rc; + return rc; + } + + return AbckitWrapperErrorCode::ERR_SUCCESS; +} + +std::string abckit_wrapper::Member::GetDescriptor() +{ + if (ABCKIT_WRAPPER_ERROR(this->RefreshSignature())) { + return ""; + } + + return this->descriptor_; +} + +std::string abckit_wrapper::Member::GetRawName() +{ + if (ABCKIT_WRAPPER_ERROR(this->RefreshSignature())) { + return ""; + } + + return this->rawName_; +} + +std::string abckit_wrapper::Member::GetSignature() +{ + if (ABCKIT_WRAPPER_ERROR(this->RefreshSignature())) { + return ""; + } + + return this->rawName_ + this->descriptor_; +} + +bool abckit_wrapper::Member::MemberAccept(MemberVisitor &visitor) +{ + return visitor.Visit(this); +} diff --git a/ark_guard/abckit_wrapper/library/member_visitor.cpp b/ark_guard/abckit_wrapper/library/member_visitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da139048d954c499d0520eb5f96304359370ec63 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/member_visitor.cpp @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "abckit_wrapper/visitor/member_visitor.h" + +#include "abckit_wrapper/member.h" + +bool abckit_wrapper::MemberFilter::Visit(Member *member) +{ + if (this->Accepted(member)) { + return member->MemberAccept(visitor_); + } + + return true; +} + +bool abckit_wrapper::MemberAccessFlagFilter::Accepted(Member *member) +{ + if ((member->GetAccessFlags() & this->rejectFlags_) != 0) { + return false; + } + + return (member->GetAccessFlags() & this->accessFlags_) != 0; +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/library/method.cpp b/ark_guard/abckit_wrapper/library/method.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d4ce8e5762d5f6bf0fe49e8ea27d8aef3ef7b18 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/method.cpp @@ -0,0 +1,196 @@ +/** + * 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 "abckit_wrapper/method.h" +#include +#include +#include "abckit_wrapper/modifiers.h" +#include "string_util.h" +#include "logger.h" + +namespace { +constexpr std::string_view RAW_NAME_AND_TYPE_NAME_SEP = ":"; +constexpr size_t RAW_NAME_AND_TYPE_NAME_SIZE = 2; +constexpr std::string_view TYPE_NAME_SEP = ";"; +const std::regex SETTER_GETTER_PATTERN(R"(<(set|get)>)"); + +bool IsSetterOrGetterMethod(const std::string &methodRawName) +{ + return std::regex_search(methodRawName, SETTER_GETTER_PATTERN); +} +} // namespace + +std::string abckit_wrapper::Parameter::GetName() const +{ + return ""; // function param name is ignored +} + +std::string abckit_wrapper::Parameter::GetTypeName() const +{ + return this->impl_.GetType().GetName(); +} + +bool abckit_wrapper::Parameter::Accept(ParameterVisitor &visitor) +{ + return visitor.Visit(this); +} + +AbckitWrapperErrorCode abckit_wrapper::Method::Init() +{ + this->InitAccessFlags(); + + auto rc = this->InitSignature(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init method descriptor for:" << this->GetFullyQualifiedName(); + return rc; + } + + LOG_I << "signature:" << this->rawName_ + this->descriptor_; + + rc = this->InitAnnotations(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init method annotations:" << rc; + return rc; + } + + rc = this->InitParameters(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init method parameters:" << rc; + return rc; + } + + return ERR_SUCCESS; +} + +std::string abckit_wrapper::Method::GetName() const +{ + return this->GetObjectName(); +} + +bool abckit_wrapper::Method::IsConstructor() const +{ + return this->impl_.IsCctor() || this->impl_.IsCtor(); +} + +AbckitWrapperErrorCode abckit_wrapper::Method::InitSignature() +{ + // split method name and params type name by ":" + const auto cachedName = this->GetName(); + const auto rawNameAndTypeName = StringUtil::Split(cachedName, RAW_NAME_AND_TYPE_NAME_SEP.data()); + if (rawNameAndTypeName.size() != RAW_NAME_AND_TYPE_NAME_SIZE) { + LOG_E << "get bad len of rawName and typeNames for method:" << cachedName; + return ERR_INNER_ERROR; + } + this->rawName_ = rawNameAndTypeName[0]; + + // setter or getter method descriptor is the field name + if (IsSetterOrGetterMethod(rawNameAndTypeName[0])) { + this->rawName_ = std::regex_replace(rawNameAndTypeName[0], SETTER_GETTER_PATTERN, ""); + this->descriptor_ = ""; + return ERR_SUCCESS; + } + + // split params type name by ";" + const auto paramsAndReturnTypeName = StringUtil::Split(rawNameAndTypeName[1], TYPE_NAME_SEP.data()); + if (paramsAndReturnTypeName.empty()) { + LOG_E << "typeNames is empty for method:" << cachedName; + return ERR_INNER_ERROR; + } + + // build descriptor + this->descriptor_ += "("; + if (paramsAndReturnTypeName.size() > 1) { + auto begin = paramsAndReturnTypeName.begin(); + // if method is not static, first param will be ignored, first param is the class full name + if (!this->impl_.IsStatic()) { + begin = std::next(begin); + } + // combine params to param1Type, param2Type, ..., paramNType + this->descriptor_ += + std::accumulate(begin, std::prev(paramsAndReturnTypeName.end()), std::string(), + [](const std::string &a, const std::string &b) { return a.empty() ? b : a + ", " + b; }); + } + this->descriptor_ += ")" + paramsAndReturnTypeName[paramsAndReturnTypeName.size() - 1]; + + this->cachedName_ = cachedName; + + return ERR_SUCCESS; +} + +void abckit_wrapper::Method::InitAccessFlags() +{ + this->accessFlags_ |= this->impl_.IsPublic() ? AccessFlags::PUBLIC : AccessFlags::NONE; + this->accessFlags_ |= this->impl_.IsProtected() ? AccessFlags::PROTECTED : AccessFlags::NONE; + this->accessFlags_ |= this->impl_.IsPrivate() ? AccessFlags::PRIVATE : AccessFlags::NONE; + this->accessFlags_ |= this->impl_.IsInternal() ? AccessFlags::INTERNAL : AccessFlags::NONE; + + this->accessFlags_ |= this->impl_.IsCctor() ? AccessFlags::CCTOR : AccessFlags::NONE; + this->accessFlags_ |= this->impl_.IsCtor() ? AccessFlags::CTOR : AccessFlags::NONE; + this->accessFlags_ |= this->impl_.IsStatic() ? AccessFlags::STATIC : AccessFlags::NONE; + + const auto function = this->GetArkTsImpl(); + this->accessFlags_ |= function.IsFinal() ? AccessFlags::FINAL : AccessFlags::NONE; + this->accessFlags_ |= function.IsAbstract() ? AccessFlags::ABSTRACT : AccessFlags::NONE; + this->accessFlags_ |= function.IsAsync() ? AccessFlags::ASYNC : AccessFlags::NONE; + // async function has the native attr, exclude the native attr for async function + this->accessFlags_ |= function.IsNative() && !function.IsAsync() ? AccessFlags::NATIVE : AccessFlags::NONE; +} + +void abckit_wrapper::Method::InitAnnotation(Annotation *annotation) +{ + annotation->owner_ = this; +} + +std::vector abckit_wrapper::Method::GetAnnotations() const +{ + return this->impl_.GetAnnotations(); +} + +AbckitWrapperErrorCode abckit_wrapper::Method::InitParameters() +{ + for (auto ¶m : this->impl_.GetParameters()) { + auto parameter = std::make_unique(param); + parameter->owingMethod_ = this; + const auto rc = parameter->Init(); + if (ABCKIT_WRAPPER_ERROR(rc)) { + LOG_E << "Failed to init parameter:" << rc; + return rc; + } + LOG_I << "Found parameter:" << parameter->GetTypeName(); + this->parameters_.emplace_back(std::move(parameter)); + } + + return ERR_SUCCESS; +} + +bool abckit_wrapper::Method::Accept(MethodVisitor &visitor) +{ + return visitor.Visit(this); +} + +bool abckit_wrapper::Method::Accept(ChildVisitor &visitor) +{ + return visitor.VisitMethod(this); +} + +bool abckit_wrapper::Method::ParametersAccept(ParameterVisitor &visitor) const +{ + for (const auto ¶m : this->parameters_) { + if (!param->Accept(visitor)) { + return false; + } + } + + return true; +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/library/modifiers.cpp b/ark_guard/abckit_wrapper/library/modifiers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..866d48a254adf20dc61b7a894becf2f7805315cd --- /dev/null +++ b/ark_guard/abckit_wrapper/library/modifiers.cpp @@ -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. + */ +#include "abckit_wrapper/modifiers.h" + +bool abckit_wrapper::AccessFlagsTarget::HasAccessFlag(const uint32_t accessFlags, const AccessFlags targetAccessFlags) +{ + return (accessFlags & targetAccessFlags) != 0; +} + +uint32_t abckit_wrapper::AccessFlagsTarget::GetAccessFlags() const +{ + return this->accessFlags_; +} diff --git a/ark_guard/abckit_wrapper/library/module.cpp b/ark_guard/abckit_wrapper/library/module.cpp index a78a85b6213fc88281489d5291b52bb27af26597..1bb15fbf855aaf9d2f39dfe9adeeb8c3a02b8d5c 100644 --- a/ark_guard/abckit_wrapper/library/module.cpp +++ b/ark_guard/abckit_wrapper/library/module.cpp @@ -14,6 +14,7 @@ */ #include "abckit_wrapper/module.h" #include "object_visitor.h" +#include "annotation_target_visitor.h" void abckit_wrapper::Module::InitForObject(Object *object) { @@ -43,7 +44,33 @@ bool abckit_wrapper::Module::NamespacesAccept(NamespaceVisitor &visitor) return this->TypedObjectsAccept(visitor); } +bool abckit_wrapper::Module::MethodsAccept(MethodVisitor &visitor) +{ + return this->TypedObjectsAccept(visitor); +} + +bool abckit_wrapper::Module::FieldsAccept(FieldVisitor &visitor) +{ + return this->TypedObjectsAccept(visitor); +} + bool abckit_wrapper::Module::ClassesAccept(ClassVisitor &visitor) { return this->TypedObjectsAccept(visitor); } + +bool abckit_wrapper::Module::AnnotationInterfacesAccept(AnnotationInterfaceVisitor &visitor) +{ + return this->TypedObjectsAccept(visitor); +} + +bool abckit_wrapper::Module::AnnotationsAccept(AnnotationVisitor &visitor) +{ + for (auto &[_, object] : this->typedObjectTable_) { + if (!std::visit(AnnotationTargetVisitor(visitor), object)) { + return false; + } + } + + return true; +} diff --git a/ark_guard/abckit_wrapper/library/module_visitor.cpp b/ark_guard/abckit_wrapper/library/module_visitor.cpp index ab4af3913de3800993bd4310b168c2204f40a00a..3d7561083bde6a151cad63f14a978b7da217667b 100644 --- a/ark_guard/abckit_wrapper/library/module_visitor.cpp +++ b/ark_guard/abckit_wrapper/library/module_visitor.cpp @@ -33,3 +33,8 @@ bool abckit_wrapper::ModuleClassVisitor::Visit(Module *module) { return module->ClassesAccept(this->visitor_); } + +bool abckit_wrapper::ModuleAnnotationVisitor::Visit(Module *module) +{ + return module->AnnotationsAccept(this->visitor_); +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/library/namespace.cpp b/ark_guard/abckit_wrapper/library/namespace.cpp index 3c0e1e025035d8fe7a519ddc23c983e8373b294a..a8d75b57c4b754090505545db741909fa2b59041 100644 --- a/ark_guard/abckit_wrapper/library/namespace.cpp +++ b/ark_guard/abckit_wrapper/library/namespace.cpp @@ -29,4 +29,4 @@ bool abckit_wrapper::Namespace::Accept(NamespaceVisitor &visitor) bool abckit_wrapper::Namespace::Accept(ChildVisitor &visitor) { return visitor.VisitNamespace(this); -} +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/library/object_visitor.cpp b/ark_guard/abckit_wrapper/library/object_visitor.cpp index 3f48ff904a2d15522cba15aac7568d2e15d27498..0d451950c699ec558df52f75e16348e3d26a5946 100644 --- a/ark_guard/abckit_wrapper/library/object_visitor.cpp +++ b/ark_guard/abckit_wrapper/library/object_visitor.cpp @@ -20,7 +20,22 @@ bool abckit_wrapper::ObjectVisitor::operator()(Namespace *ns) const return this->Accept(ns); } +bool abckit_wrapper::ObjectVisitor::operator()(Method *method) const +{ + return this->Accept(method); +} + +bool abckit_wrapper::ObjectVisitor::operator()(Field *field) const +{ + return this->Accept(field); +} + bool abckit_wrapper::ObjectVisitor::operator()(Class *clazz) const { return this->Accept(clazz); } + +bool abckit_wrapper::ObjectVisitor::operator()(AnnotationInterface *ai) const +{ + return this->Accept(ai); +} diff --git a/ark_guard/abckit_wrapper/library/object_visitor.h b/ark_guard/abckit_wrapper/library/object_visitor.h index 0d6a340a3f8e4438d9bce32662cd49b5556021d4..f7d0e5959b996bbcbd45cf8cfae2f7e513d30f42 100644 --- a/ark_guard/abckit_wrapper/library/object_visitor.h +++ b/ark_guard/abckit_wrapper/library/object_visitor.h @@ -33,12 +33,30 @@ public: */ explicit ObjectVisitor(NamespaceVisitor *visitor) : visitor_(visitor) {} + /** + * @brief ObjectVisitor Constructor + * @param visitor MethodVisitor + */ + explicit ObjectVisitor(MethodVisitor *visitor) : visitor_(visitor) {} + + /** + * @brief ObjectVisitor Constructor + * @param visitor FieldVisitor + */ + explicit ObjectVisitor(FieldVisitor *visitor) : visitor_(visitor) {} + /** * @brief ObjectVisitor Constructor * @param visitor ClassVisitor */ explicit ObjectVisitor(ClassVisitor *visitor) : visitor_(visitor) {} + /** + * @brief ObjectVisitor Constructor + * @param visitor ClassVisitor + */ + explicit ObjectVisitor(AnnotationInterfaceVisitor *visitor) : visitor_(visitor) {} + /** * @brief ObjectVisitor Constructor * @param childVisitor ChildVisitor @@ -52,6 +70,20 @@ public: */ bool operator()(Namespace *ns) const; + /** + * @brief Visit method + * @param method visited method + * @return `false` if was early exited. Otherwise - `true`. + */ + bool operator()(Method *method) const; + + /** + * @brief Visit field + * @param field visited field + * @return `false` if was early exited. Otherwise - `true`. + */ + bool operator()(Field *field) const; + /** * @brief Visit class * @param clazz visited class @@ -59,6 +91,13 @@ public: */ bool operator()(Class *clazz) const; + /** + * @brief Visit annotationInterface + * @param ai annotationInterface + * @return `false` if was early exited. Otherwise - `true`. + */ + bool operator()(AnnotationInterface *ai) const; + /** * Accept instance accept with instance visitor * @tparam InstanceType instance type @@ -81,7 +120,8 @@ public: } private: - std::variant visitor_; + std::variant + visitor_; ChildVisitor *childVisitor_ = nullptr; }; } // namespace abckit_wrapper diff --git a/ark_guard/abckit_wrapper/library/string_util.cpp b/ark_guard/abckit_wrapper/library/string_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a1497a7f58f643a634efd1fd84108745461bf25 --- /dev/null +++ b/ark_guard/abckit_wrapper/library/string_util.cpp @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "string_util.h" + +std::vector abckit_wrapper::StringUtil::Split(const std::string &str, const std::string &delimiter) +{ + std::vector tokens; + auto start = str.find_first_not_of(delimiter, 0); + auto pos = str.find_first_of(delimiter, 0); + while (start != std::string::npos) { + if (pos > start) { + tokens.push_back(str.substr(start, pos - start)); + } + start = str.find_first_not_of(delimiter, pos); + pos = str.find_first_of(delimiter, start + 1); + } + + return tokens; +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/library/string_util.h b/ark_guard/abckit_wrapper/library/string_util.h new file mode 100644 index 0000000000000000000000000000000000000000..32cbf50215f183fcfb8892249d5149c6846a1eab --- /dev/null +++ b/ark_guard/abckit_wrapper/library/string_util.h @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABCKIT_WRAPPER_STRING_UTIL_H +#define ABCKIT_WRAPPER_STRING_UTIL_H + +#include +#include + +namespace abckit_wrapper { +class StringUtil { +public: + /** + * Split str by delimiter + * @param str split str + * @param delimiter split delimiter + * @return split tokens, if split failed return empty vector + * e.g. Split("##a#", "#"); => ["a"] + */ + static std::vector Split(const std::string &str, const std::string &delimiter); +}; +} // namespace abckit_wrapper + +#endif // ABCKIT_WRAPPER_STRING_UTIL_H diff --git a/ark_guard/abckit_wrapper/tests/BUILD.gn b/ark_guard/abckit_wrapper/tests/BUILD.gn index d094d7ca3541c260376c17ac2dcb1e9bae1688b2..af096a9f7709818ed710b8daf4ec7ca328c8d35b 100755 --- a/ark_guard/abckit_wrapper/tests/BUILD.gn +++ b/ark_guard/abckit_wrapper/tests/BUILD.gn @@ -18,6 +18,11 @@ import("$ark_root/tests/test_helper.gni") test_ets_path = "$ark_root/ark_guard/abckit_wrapper/tests/" test_ets_files = [ + "ut/access_flag_test", + "ut/annotation_test", + "ut/class_hierarchy", + "ut/field_test", + "ut/method_param_test", "ut/module_static", ] @@ -40,7 +45,14 @@ host_unittest_action("AbckitWrapperUnitTest") { module_out_path = "$ark_root" sources = [ + "ut/access_flag_test.cpp", + "ut/annotation_test.cpp", + "ut/class_hierarchy_test.cpp", + "ut/field_test.cpp", "ut/file_view_test.cpp", + "ut/hierarchy_dumper_test.cpp", + "ut/logger_test.cpp", + "ut/method_param_test.cpp", "ut/visitor_test.cpp", ] diff --git a/ark_guard/abckit_wrapper/tests/ut/access_flag_test.cpp b/ark_guard/abckit_wrapper/tests/ut/access_flag_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4288b7f0925950d7f6609e325192d9bc37ebd032 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/access_flag_test.cpp @@ -0,0 +1,538 @@ +/** + * 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 "abckit_wrapper/file_view.h" +#include "test_util/assert.h" +#include "../../library/logger.h" + +using namespace testing::ext; + +namespace { +constexpr std::string_view ABC_FILE_PATH = ABCKIT_WRAPPER_ABC_FILE_DIR "ut/access_flag_test.abc"; +abckit_wrapper::FileView fileView; +} // namespace + +static void AssertHasAccessFlags(const uint32_t accessFlags, const abckit_wrapper::AccessFlags targetAccessFlags) +{ + LOG_I << "accessFlags:" << accessFlags; + LOG_I << "targetAccessFlags:" << targetAccessFlags; + ASSERT_TRUE(abckit_wrapper::AccessFlagsTarget::HasAccessFlag(accessFlags, targetAccessFlags)); +} + +class TestAccessFlag : public ::testing::Test { +public: + static void SetUpTestSuite() + { + ASSERT_SUCCESS(fileView.Init(ABC_FILE_PATH)); + } +}; + +/** + * @tc.name: method_access_flags_001 + * @tc.desc: test method access flags PUBLIC PROTECTED PRIVATE INTERNAL + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_001, TestSize.Level4) +{ + // public + const auto method1 = + fileView.Get("access_flag_test.ClassA.method1:access_flag_test.ClassA;void;"); + ASSERT_TRUE(method1.has_value()); + AssertHasAccessFlags(method1.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::PUBLIC); + // protected + const auto method2 = + fileView.Get("access_flag_test.ClassA.method2:access_flag_test.ClassA;void;"); + ASSERT_TRUE(method2.has_value()); + AssertHasAccessFlags(method2.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::PROTECTED); + // private + const auto method3 = + fileView.Get("access_flag_test.ClassA.method3:access_flag_test.ClassA;void;"); + ASSERT_TRUE(method3.has_value()); + AssertHasAccessFlags(method3.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::PRIVATE); + // internal + const auto method4 = + fileView.Get("access_flag_test.ClassA.method4:access_flag_test.ClassA;void;"); + ASSERT_TRUE(method4.has_value()); + AssertHasAccessFlags(method4.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::INTERNAL); +} + +/** + * @tc.name: method_access_flags_002 + * @tc.desc: test method access flags FINAL ABSTRACT ASYNC NATIVE + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_002, TestSize.Level4) +{ + // final + const auto method0 = + fileView.Get("access_flag_test.ClassB.method0:access_flag_test.ClassB;void;"); + ASSERT_TRUE(method0.has_value()); + AssertHasAccessFlags(method0.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::FINAL); + // abstract + const auto method1 = + fileView.Get("access_flag_test.ClassB.method1:access_flag_test.ClassB;void;"); + ASSERT_TRUE(method1.has_value()); + AssertHasAccessFlags(method1.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::ABSTRACT); + // async + const auto method2 = fileView.Get( + "access_flag_test.ClassB.method2:access_flag_test.ClassB;std.core.Promise;"); + ASSERT_TRUE(method2.has_value()); + AssertHasAccessFlags(method2.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::ASYNC); + // native + const auto method3 = + fileView.Get("access_flag_test.ClassB.method3:access_flag_test.ClassB;void;"); + ASSERT_TRUE(method3.has_value()); + AssertHasAccessFlags(method3.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::NATIVE); +} + +class TestMemberAccessFlagVisitor final : public abckit_wrapper::MemberVisitor { +public: + bool Visit(abckit_wrapper::Member *member) override + { + LOG_I << "memberName:" << member->GetFullyQualifiedName(); + this->members_.emplace_back(member); + return true; + } + + std::vector members_; +}; + +/** + * @tc.name: method_access_flags_003 + * @tc.desc: test member access filter the public method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_003, TestSize.Level4) +{ + const auto classA = fileView.Get("access_flag_test.ClassA"); + const auto method1 = + fileView.Get("access_flag_test.ClassA.method1:access_flag_test.ClassA;void;"); + ASSERT_TRUE(classA.has_value()); + ASSERT_TRUE(method1.has_value()); + TestMemberAccessFlagVisitor visitor; + // ignore static and ctor method + ASSERT_TRUE(classA.value()->MembersAccept(visitor.Wrap( + abckit_wrapper::AccessFlags::PUBLIC, abckit_wrapper::AccessFlags::STATIC | abckit_wrapper::AccessFlags::CTOR))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method1.value()); +} + +/** + * @tc.name: method_access_flags_004 + * @tc.desc: test member access filter the protected method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_004, TestSize.Level4) +{ + const auto classA = fileView.Get("access_flag_test.ClassA"); + const auto method2 = + fileView.Get("access_flag_test.ClassA.method2:access_flag_test.ClassA;void;"); + ASSERT_TRUE(classA.has_value()); + ASSERT_TRUE(method2.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classA.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::PROTECTED))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method2.value()); +} + +/** + * @tc.name: method_access_flags_005 + * @tc.desc: test member access filter the private method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_005, TestSize.Level4) +{ + const auto classA = fileView.Get("access_flag_test.ClassA"); + const auto method3 = + fileView.Get("access_flag_test.ClassA.method3:access_flag_test.ClassA;void;"); + ASSERT_TRUE(classA.has_value()); + ASSERT_TRUE(method3.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classA.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::PRIVATE))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method3.value()); +} + +/** + * @tc.name: method_access_flags_006 + * @tc.desc: test member access filter the internal method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_006, TestSize.Level4) +{ + const auto classA = fileView.Get("access_flag_test.ClassA"); + const auto method4 = + fileView.Get("access_flag_test.ClassA.method4:access_flag_test.ClassA;void;"); + ASSERT_TRUE(classA.has_value()); + ASSERT_TRUE(method4.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classA.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::INTERNAL))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method4.value()); +} + +/** + * @tc.name: method_access_flags_007 + * @tc.desc: test method access flags CTOR(instance constructor) + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_007, TestSize.Level4) +{ + // ctor + const auto _ctor_ = + fileView.Get("access_flag_test.ClassA._ctor_:access_flag_test.ClassA;void;"); + ASSERT_TRUE(_ctor_.has_value()); + AssertHasAccessFlags(_ctor_.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::CTOR); +} + +/** + * @tc.name: method_access_flags_008 + * @tc.desc: test member access filter the _ctor_ member + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_008, TestSize.Level4) +{ + const auto classA = fileView.Get("access_flag_test.ClassA"); + const auto _ctor_ = + fileView.Get("access_flag_test.ClassA._ctor_:access_flag_test.ClassA;void;"); + ASSERT_TRUE(classA.has_value()); + ASSERT_TRUE(_ctor_.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classA.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::CTOR))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], _ctor_.value()); +} + +/** + * @tc.name: method_access_flags_009 + * @tc.desc: test method access flags STATIC + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_009, TestSize.Level4) +{ + // static method + const auto method0 = fileView.Get("access_flag_test.ClassA.method0:void;"); + ASSERT_TRUE(method0.has_value()); + AssertHasAccessFlags(method0.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::STATIC); +} + +/** + * @tc.name: method_access_flags_010 + * @tc.desc: test member access filter the static method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_010, TestSize.Level4) +{ + const auto classA = fileView.Get("access_flag_test.ClassA"); + const auto method0 = fileView.Get("access_flag_test.ClassA.method0:void;"); + ASSERT_TRUE(classA.has_value()); + ASSERT_TRUE(method0.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classA.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::STATIC))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method0.value()); +} + +/** + * @tc.name: method_access_flags_011 + * @tc.desc: test member access filter the final method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_011, TestSize.Level4) +{ + const auto classB = fileView.Get("access_flag_test.ClassB"); + const auto method0 = + fileView.Get("access_flag_test.ClassB.method0:access_flag_test.ClassB;void;"); + ASSERT_TRUE(classB.has_value()); + ASSERT_TRUE(method0.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classB.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::FINAL))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method0.value()); +} + +/** + * @tc.name: method_access_flags_012 + * @tc.desc: test member access filter the abstract method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_012, TestSize.Level4) +{ + const auto classB = fileView.Get("access_flag_test.ClassB"); + const auto method1 = + fileView.Get("access_flag_test.ClassB.method1:access_flag_test.ClassB;void;"); + ASSERT_TRUE(classB.has_value()); + ASSERT_TRUE(method1.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classB.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::ABSTRACT))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method1.value()); +} + +/** + * @tc.name: method_access_flags_013 + * @tc.desc: test member access filter the final method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_013, TestSize.Level4) +{ + const auto classB = fileView.Get("access_flag_test.ClassB"); + const auto method2 = fileView.Get( + "access_flag_test.ClassB.method2:access_flag_test.ClassB;std.core.Promise;"); + ASSERT_TRUE(classB.has_value()); + ASSERT_TRUE(method2.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classB.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::ASYNC))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method2.value()); +} + +/** + * @tc.name: method_access_flags_014 + * @tc.desc: test member access filter the final method + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_014, TestSize.Level4) +{ + const auto classB = fileView.Get("access_flag_test.ClassB"); + const auto method3 = + fileView.Get("access_flag_test.ClassB.method3:access_flag_test.ClassB;void;"); + ASSERT_TRUE(classB.has_value()); + ASSERT_TRUE(method3.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classB.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::NATIVE))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], method3.value()); +} + +/** + * @tc.name: method_access_flags_015 + * @tc.desc: test method access flags CCTOR(static constructor) + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_015, TestSize.Level4) +{ + // cctor + const auto _ctor_ = fileView.Get("access_flag_test.ClassC._cctor_:void;"); + ASSERT_TRUE(_ctor_.has_value()); + AssertHasAccessFlags(_ctor_.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::CCTOR); +} + +/** + * @tc.name: method_access_flags_016 + * @tc.desc: test member access filter the _cctor_ member + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, method_access_flags_016, TestSize.Level4) +{ + const auto classC = fileView.Get("access_flag_test.ClassC"); + const auto _cctor_ = fileView.Get("access_flag_test.ClassC._cctor_:void;"); + ASSERT_TRUE(classC.has_value()); + ASSERT_TRUE(_cctor_.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classC.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::CCTOR))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], _cctor_.value()); +} + +/** + * @tc.name: field_access_flags_001 + * @tc.desc: test field access flags PUBLIC PROTECTED PRIVATE INTERNAL + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, field_access_flags_001, TestSize.Level4) +{ + // public + const auto field1 = fileView.Get("access_flag_test.ClassC.field1"); + ASSERT_TRUE(field1.has_value()); + AssertHasAccessFlags(field1.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::PUBLIC); + // protected + const auto field2 = fileView.Get("access_flag_test.ClassC.field2"); + ASSERT_TRUE(field2.has_value()); + AssertHasAccessFlags(field2.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::PROTECTED); + // private + const auto field3 = fileView.Get("access_flag_test.ClassC.field3"); + ASSERT_TRUE(field3.has_value()); + AssertHasAccessFlags(field3.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::PRIVATE); + // internal + const auto field4 = fileView.Get("access_flag_test.ClassC.field4"); + ASSERT_TRUE(field4.has_value()); + AssertHasAccessFlags(field4.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::INTERNAL); +} + +/** + * @tc.name: field_access_flags_002 + * @tc.desc: test method access flags STATIC + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, field_access_flags_002, TestSize.Level4) +{ + // static field + const auto field0 = fileView.Get("access_flag_test.ClassC.field0"); + ASSERT_TRUE(field0.has_value()); + AssertHasAccessFlags(field0.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::STATIC); +} + +/** + * @tc.name: field_access_flags_003 + * @tc.desc: test member access filter the public field + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, field_access_flags_003, TestSize.Level4) +{ + const auto classC = fileView.Get("access_flag_test.ClassC"); + const auto field1 = fileView.Get("access_flag_test.ClassC.field1"); + ASSERT_TRUE(classC.has_value()); + ASSERT_TRUE(field1.has_value()); + TestMemberAccessFlagVisitor visitor; + // ignore static field and ctor method + ASSERT_TRUE(classC.value()->MembersAccept(visitor.Wrap( + abckit_wrapper::AccessFlags::PUBLIC, abckit_wrapper::AccessFlags::CTOR | abckit_wrapper::AccessFlags::STATIC))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], field1.value()); +} + +/** + * @tc.name: field_access_flags_004 + * @tc.desc: test member access filter the protected field + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, field_access_flags_004, TestSize.Level4) +{ + const auto classC = fileView.Get("access_flag_test.ClassC"); + const auto field2 = fileView.Get("access_flag_test.ClassC.field2"); + ASSERT_TRUE(classC.has_value()); + ASSERT_TRUE(field2.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classC.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::PROTECTED))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], field2.value()); +} + +/** + * @tc.name: field_access_flags_005 + * @tc.desc: test member access filter the private field + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, field_access_flags_005, TestSize.Level4) +{ + const auto classC = fileView.Get("access_flag_test.ClassC"); + const auto field3 = fileView.Get("access_flag_test.ClassC.field3"); + ASSERT_TRUE(classC.has_value()); + ASSERT_TRUE(field3.has_value()); + TestMemberAccessFlagVisitor visitor; + ASSERT_TRUE(classC.value()->MembersAccept( + visitor.Wrap(abckit_wrapper::AccessFlags::PRIVATE))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], field3.value()); +} + +/** + * @tc.name: field_access_flags_006 + * @tc.desc: test member access filter the internal field + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, field_access_flags_006, TestSize.Level4) +{ + const auto classC = fileView.Get("access_flag_test.ClassC"); + const auto field4 = fileView.Get("access_flag_test.ClassC.field4"); + ASSERT_TRUE(classC.has_value()); + ASSERT_TRUE(field4.has_value()); + TestMemberAccessFlagVisitor visitor; + // ignore cctor + ASSERT_TRUE(classC.value()->MembersAccept(visitor.Wrap( + abckit_wrapper::AccessFlags::INTERNAL, abckit_wrapper::AccessFlags::CCTOR))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], field4.value()); +} + +/** + * @tc.name: field_access_flags_007 + * @tc.desc: test member access filter the static field + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, field_access_flags_007, TestSize.Level4) +{ + const auto classC = fileView.Get("access_flag_test.ClassC"); + const auto field0 = fileView.Get("access_flag_test.ClassC.field0"); + ASSERT_TRUE(classC.has_value()); + ASSERT_TRUE(field0.has_value()); + TestMemberAccessFlagVisitor visitor; + // ignore cctor + ASSERT_TRUE(classC.value()->MembersAccept(visitor.Wrap( + abckit_wrapper::AccessFlags::STATIC, abckit_wrapper::AccessFlags::CCTOR))); + ASSERT_TRUE(visitor.members_.size() == 1); + ASSERT_EQ(visitor.members_[0], field0.value()); +} + +/** + * @tc.name: class_access_flags_001 + * @tc.desc: test class access flags FINAL + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, class_access_flags_001, TestSize.Level4) +{ + const auto finalClass = fileView.Get("access_flag_test.FinalClass"); + ASSERT_TRUE(finalClass.has_value()); + AssertHasAccessFlags(finalClass.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::FINAL); +} + +/** + * @tc.name: class_access_flags_002 + * @tc.desc: test class access flags ABSTRACT + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAccessFlag, class_access_flags_002, TestSize.Level4) +{ + const auto abstractClass = fileView.Get("access_flag_test.AbstractClass"); + ASSERT_TRUE(abstractClass.has_value()); + AssertHasAccessFlags(abstractClass.value()->GetAccessFlags(), abckit_wrapper::AccessFlags::ABSTRACT); +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/access_flag_test.ets b/ark_guard/abckit_wrapper/tests/ut/access_flag_test.ets new file mode 100644 index 0000000000000000000000000000000000000000..6a10cbcadaae72ab7096f19a3f3c898c5416719b --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/access_flag_test.ets @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +abstract class AbstractClass { +} + +final class FinalClass { +} + +class ClassA { + public static method0() { + } + + public method1() { + } + + protected method2() { + } + + private method3() { + } + + internal method4() { + } +} + +abstract class ClassB { + public final method0() { + } + + public abstract method1(); + + public async method2() { + } + + public native method3(): void; +} + +class ClassC { + public static field0: int; + public field1: int; + protected field2: int; + private field3: int; + internal field4: int; +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/annotation_test.cpp b/ark_guard/abckit_wrapper/tests/ut/annotation_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd341b22e90f64f6845e738985de1ae40a5d6ec1 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/annotation_test.cpp @@ -0,0 +1,213 @@ +/** + * 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 "abckit_wrapper/file_view.h" +#include "test_util/assert.h" +#include "../../library/logger.h" + +using namespace testing::ext; + +namespace { +constexpr std::string_view ABC_FILE_PATH = ABCKIT_WRAPPER_ABC_FILE_DIR "ut/annotation_test.abc"; +abckit_wrapper::FileView fileView; +} // namespace + +class TestBaseAnnotationVisitor : public abckit_wrapper::AnnotationVisitor { +public: + void AddAnnotationName(const std::string &annotationName) + { + this->targetAnnotationNames_.insert(annotationName); + } + + virtual void InitTargetAnnotationNames() = 0; + + bool Visit(abckit_wrapper::Annotation *annotation) override + { + LOG_I << "AnnotationName:" << annotation->GetFullyQualifiedName(); + this->annotations_.emplace_back(annotation); + return true; + } + + void Validate() + { + this->InitTargetAnnotationNames(); + for (const auto &annotation : this->annotations_) { + ASSERT_TRUE(this->targetAnnotationNames_.find(annotation->GetName()) != this->targetAnnotationNames_.end()); + } + } + +private: + std::vector annotations_; + std::set targetAnnotationNames_; +}; + +class TestAnnotation : public ::testing::Test { +public: + static void SetUpTestSuite() + { + ASSERT_SUCCESS(fileView.Init(ABC_FILE_PATH)); + } + + void TearDown() override + { + ASSERT_TRUE(this->visitor_ != nullptr); + this->visitor_->Validate(); + } + +protected: + std::unique_ptr visitor_ = nullptr; +}; + +class TestClassAnnotationVisitor final : public TestBaseAnnotationVisitor { +public: + void InitTargetAnnotationNames() override + { + AddAnnotationName("MyAnno1"); + AddAnnotationName("MyAnno2"); + } +}; + +/** + * @tc.name: annotation_001 + * @tc.desc: test visit class annotation + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAnnotation, annotation_001, TestSize.Level0) +{ + const auto clazz = fileView.Get("annotation_test.ClassA"); + ASSERT_TRUE(clazz.has_value()); + + visitor_ = std::make_unique(); + clazz.value()->AnnotationsAccept(*visitor_); +} + +class TestInterfaceAnnotationVisitor final : public TestBaseAnnotationVisitor { +public: + void InitTargetAnnotationNames() override + { + AddAnnotationName("MyAnno1"); + AddAnnotationName("MyAnno2"); + } +}; + +/** + * @tc.name: annotation_002 + * @tc.desc: test visit interface annotation + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAnnotation, annotation_002, TestSize.Level0) +{ + const auto interface1 = fileView.Get("annotation_test.Interface1"); + ASSERT_TRUE(interface1.has_value()); + + visitor_ = std::make_unique(); + interface1.value()->AnnotationsAccept(*visitor_); +} + +class TestClassFieldAnnotationVisitor final : public TestBaseAnnotationVisitor { +public: + void InitTargetAnnotationNames() override + { + AddAnnotationName("MyAnno1"); + } +}; + +/** + * @tc.name: annotation_003 + * @tc.desc: test visit class field annotation + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAnnotation, annotation_003, TestSize.Level0) +{ + const auto field1 = fileView.Get("annotation_test.ClassA.field1"); + ASSERT_TRUE(field1.has_value()); + + visitor_ = std::make_unique(); + field1.value()->AnnotationsAccept(*visitor_); +} + +class TestClassMethodAnnotationVisitor final : public TestBaseAnnotationVisitor { +public: + void InitTargetAnnotationNames() override + { + AddAnnotationName("MyAnno1"); + } +}; + +/** + * @tc.name: annotation_004 + * @tc.desc: test visit class method annotation + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAnnotation, annotation_004, TestSize.Level0) +{ + const auto method1 = + fileView.Get("annotation_test.ClassA.method1:annotation_test.ClassA;void;"); + ASSERT_TRUE(method1.has_value()); + + visitor_ = std::make_unique(); + method1.value()->AnnotationsAccept(*visitor_); +} + +class TestInterfaceFieldAnnotationVisitor final : public TestBaseAnnotationVisitor { +public: + void InitTargetAnnotationNames() override + { + AddAnnotationName("MyAnno1"); + } +}; + +/** + * @tc.name: annotation_005 + * @tc.desc: test visit interface field annotation + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAnnotation, annotation_005, TestSize.Level0) +{ + const auto field1 = fileView.Get("annotation_test.Interface1.iField1"); + ASSERT_TRUE(field1.has_value()); + + visitor_ = std::make_unique(); + field1.value()->AnnotationsAccept(*visitor_); +} + +class TestInterfaceMethodAnnotationVisitor final : public TestBaseAnnotationVisitor { +public: + void InitTargetAnnotationNames() override + { + AddAnnotationName("MyAnno1"); + } +}; + +/** + * @tc.name: annotation_006 + * @tc.desc: test visit interface method annotation + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestAnnotation, annotation_006, TestSize.Level0) +{ + const auto method1 = + fileView.Get("annotation_test.Interface1.iMethod1:annotation_test.Interface1;void;"); + ASSERT_TRUE(method1.has_value()); + + visitor_ = std::make_unique(); + method1.value()->AnnotationsAccept(*visitor_); +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/annotation_test.ets b/ark_guard/abckit_wrapper/tests/ut/annotation_test.ets new file mode 100644 index 0000000000000000000000000000000000000000..23697cea6512b442b61774207a63752d47c55d14 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/annotation_test.ets @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@interface MyAnno1 { +} + +@interface MyAnno2 { +} + +@MyAnno1() +@MyAnno2() +class ClassA { + @MyAnno1() + public field1 = 1; + + @MyAnno1() + public method1() { + } +} + +@MyAnno1() +@MyAnno2() +interface Interface1 { + @MyAnno1() + iField1: int; + + @MyAnno1() + iMethod1(); +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/class_hierarchy.ets b/ark_guard/abckit_wrapper/tests/ut/class_hierarchy.ets new file mode 100644 index 0000000000000000000000000000000000000000..d083d7c07f44d120c7e6846a62fe837dfba36639 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/class_hierarchy.ets @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +interface Interface1 { +} + +interface Interface2 { +} + +interface Interface3 extends Interface1 { +} + +class ClassA implements Interface1 { +} + +class ClassB extends ClassA implements Interface2 { +} + +class ClassC extends ClassB implements Interface3 { +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/class_hierarchy_test.cpp b/ark_guard/abckit_wrapper/tests/ut/class_hierarchy_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34f24723c5ecf531e37fd2a4bc20891f4259812d --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/class_hierarchy_test.cpp @@ -0,0 +1,255 @@ +/** + * 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 "abckit_wrapper/file_view.h" +#include "test_util/assert.h" +#include "../../library/logger.h" + +using namespace testing::ext; + +namespace { +constexpr std::string_view ABC_FILE_PATH = ABCKIT_WRAPPER_ABC_FILE_DIR "ut/class_hierarchy.abc"; +abckit_wrapper::FileView fileView; +} // namespace + +/** + * @brief Assert whether classA extends classB + * @param classA classA + * @param classB classB + * @return `true` classA extends classB + */ +static void AssertIsSuperClass(const abckit_wrapper::Class *classA, const abckit_wrapper::Class *classB) +{ + ASSERT_TRUE(classA->superClass_.has_value()); + ASSERT_EQ(classA->superClass_.value(), classB); + ASSERT_TRUE(classB->subClasses_.find(classA->GetFullyQualifiedName()) != classB->subClasses_.end()); +} + +/** + * @brief Assert whether class implement the given interfaces + * @param clazz Class + * @param interface interface + */ +static void AssertIsImplemented(const abckit_wrapper::Class *clazz, const abckit_wrapper::Class *interface) +{ + ASSERT_TRUE(clazz->interfaces_.find(interface->GetFullyQualifiedName()) != clazz->interfaces_.end()); + ASSERT_TRUE(interface->subClasses_.find(clazz->GetFullyQualifiedName()) != interface->subClasses_.end()); +} + +class TestClassHierarchyVisitor : public abckit_wrapper::ClassVisitor { +public: + virtual void InitTargetClassNames() = 0; + + void AddTargetClassName(const std::string &className) + { + this->targetClassNames_.insert(className); + } + + bool Visit(abckit_wrapper::Class *clazz) override + { + this->classes_.emplace_back(clazz); + return true; + } + + void Validate() + { + this->InitTargetClassNames(); + for (const auto &clazz : this->classes_) { + ASSERT_TRUE(this->targetClassNames_.find(clazz->GetFullyQualifiedName()) != this->targetClassNames_.end()); + } + } + +private: + std::set targetClassNames_; + std::vector classes_; +}; + +class TestClassHierarchy : public ::testing::Test { +public: + static void SetUpTestSuite() + { + ASSERT_SUCCESS(fileView.Init(ABC_FILE_PATH)); + } + + void TearDown() override + { + if (this->visitor_ != nullptr) { + } + } + +protected: + std::unique_ptr visitor_ = nullptr; +}; + +/** + * @tc.name: class_hierarchy_001 + * @tc.desc: test class hierarchy for super class + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestClassHierarchy, class_hierarchy_001, TestSize.Level0) +{ + // ClassA + const auto classA = fileView.Get("class_hierarchy.ClassA"); + ASSERT_TRUE(classA.has_value()); + // ClassB + const auto classB = fileView.Get("class_hierarchy.ClassB"); + ASSERT_TRUE(classB.has_value()); + // ClassC + const auto classC = fileView.Get("class_hierarchy.ClassC"); + ASSERT_TRUE(classC.has_value()); + + AssertIsSuperClass(classB.value(), classA.value()); + AssertIsSuperClass(classC.value(), classB.value()); +} + +/** + * @tc.name: class_hierarchy_002 + * @tc.desc: test class hierarchy for interfaces + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestClassHierarchy, class_hierarchy_002, TestSize.Level0) +{ + // ClassA + const auto classA = fileView.Get("class_hierarchy.ClassA"); + ASSERT_TRUE(classA.has_value()); + // ClassB + const auto classB = fileView.Get("class_hierarchy.ClassB"); + ASSERT_TRUE(classB.has_value()); + // ClassC + const auto classC = fileView.Get("class_hierarchy.ClassC"); + ASSERT_TRUE(classC.has_value()); + + // Interface1 + const auto interface1 = fileView.Get("class_hierarchy.Interface1"); + ASSERT_TRUE(interface1.has_value()); + // Interface2 + const auto interface2 = fileView.Get("class_hierarchy.Interface2"); + ASSERT_TRUE(interface2.has_value()); + // ClassC + const auto interface3 = fileView.Get("class_hierarchy.Interface3"); + ASSERT_TRUE(interface3.has_value()); + + AssertIsImplemented(classA.value(), interface1.value()); + AssertIsImplemented(classB.value(), interface2.value()); + AssertIsImplemented(classC.value(), interface3.value()); + AssertIsImplemented(interface3.value(), interface1.value()); +} + +class TestClassHierarchyAllVisitor final : public TestClassHierarchyVisitor { +public: + void InitTargetClassNames() override + { + AddTargetClassName("class_hierarchy.ClassA"); + AddTargetClassName("class_hierarchy.ClassB"); + AddTargetClassName("class_hierarchy.ClassC"); + AddTargetClassName("class_hierarchy.Interface1"); + AddTargetClassName("class_hierarchy.Interface2"); + AddTargetClassName("class_hierarchy.Interface3"); + } +}; + +/** + * @tc.name: class_hierarchy_003 + * @tc.desc: test class hierarchy visit all class + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestClassHierarchy, class_hierarchy_003, TestSize.Level0) +{ + // ClassB + const auto clazz = fileView.Get("class_hierarchy.ClassB"); + ASSERT_TRUE(clazz.has_value()); + + visitor_ = std::make_unique(); + clazz.value()->HierarchyAccept(*visitor_, true, true, true, true); +} + +class TestClassHierarchySuperClassVisitor final : public TestClassHierarchyVisitor { +public: + void InitTargetClassNames() override + { + AddTargetClassName("class_hierarchy.ClassA"); + AddTargetClassName("class_hierarchy.ClassB"); + } +}; + +/** + * @tc.name: class_hierarchy_004 + * @tc.desc: test class hierarchy visit super class + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestClassHierarchy, class_hierarchy_004, TestSize.Level0) +{ + // ClassC + const auto clazz = fileView.Get("class_hierarchy.ClassC"); + ASSERT_TRUE(clazz.has_value()); + + visitor_ = std::make_unique(); + clazz.value()->HierarchyAccept(*visitor_, false, true, false, false); +} + +class TestClassHierarchyInterfacesVisitor final : public TestClassHierarchyVisitor { +public: + void InitTargetClassNames() override + { + AddTargetClassName("class_hierarchy.Interface1"); + AddTargetClassName("class_hierarchy.Interface2"); + AddTargetClassName("class_hierarchy.Interface3"); + } +}; + +/** + * @tc.name: class_hierarchy_005 + * @tc.desc: test class hierarchy visit interfaces + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestClassHierarchy, class_hierarchy_005, TestSize.Level0) +{ + // ClassC + const auto clazz = fileView.Get("class_hierarchy.ClassC"); + ASSERT_TRUE(clazz.has_value()); + + visitor_ = std::make_unique(); + clazz.value()->HierarchyAccept(*visitor_, false, false, true, false); +} + +class TestClassHierarchySubClassesVisitor final : public TestClassHierarchyVisitor { +public: + void InitTargetClassNames() override + { + AddTargetClassName("class_hierarchy.ClassB"); + AddTargetClassName("class_hierarchy.ClassC"); + } +}; + +/** + * @tc.name: class_hierarchy_006 + * @tc.desc: test class hierarchy visit subClasses + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestClassHierarchy, class_hierarchy_006, TestSize.Level0) +{ + // ClassC + const auto clazz = fileView.Get("class_hierarchy.ClassA"); + ASSERT_TRUE(clazz.has_value()); + + visitor_ = std::make_unique(); + clazz.value()->HierarchyAccept(*visitor_, false, false, false, true); +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/field_test.cpp b/ark_guard/abckit_wrapper/tests/ut/field_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da9a9237f413803accc4beaf6fe8d3ff8cf32cd0 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/field_test.cpp @@ -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. + */ +#include +#include "abckit_wrapper/file_view.h" +#include "test_util/assert.h" +#include "../../library/logger.h" + +using namespace testing::ext; + +namespace { +constexpr std::string_view ABC_FILE_PATH = ABCKIT_WRAPPER_ABC_FILE_DIR "ut/field_test.abc"; + +void AssertFieldType(const abckit_wrapper::FileView &fileView, const std::string &name, const std::string &type) +{ + const auto object = fileView.Get(name); + ASSERT_TRUE(object.has_value()); + const auto fieldType = object.value()->GetType(); + ASSERT_EQ(fieldType, type) << "field type not match, expected:" << type << ", actual:" << fieldType; +} + +} // namespace + +/** + * @tc.name: field_type_test_001 + * @tc.desc: test class field get type + * @tc.type: FUNC + * @tc.require: + */ +HWTEST(TestField, field_type_test_001, TestSize.Level0) +{ + abckit_wrapper::FileView fileView; + + ASSERT_SUCCESS(fileView.Init(ABC_FILE_PATH)); + + AssertFieldType(fileView, "field_test.ClassA.field1", "i32"); + AssertFieldType(fileView, "field_test.ClassA.field2", "std.core.String"); + + AssertFieldType(fileView, "field_test.ClassB.field1", "field_test.ClassA"); + AssertFieldType(fileView, "field_test.ClassB.field2", "{Ufield_test.ClassA,std.core.String}"); +} diff --git a/ark_guard/abckit_wrapper/tests/ut/field_test.ets b/ark_guard/abckit_wrapper/tests/ut/field_test.ets new file mode 100644 index 0000000000000000000000000000000000000000..b07e02a8fdcfe0744d3c70eccb28a52d48cb3171 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/field_test.ets @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class ClassA { + public field1 = 1; + + public field2 = 'hello'; +} + +class ClassB { + public field1: ClassA; + public field2: ClassA | string; + + public constructor(field1: ClassA, field2: ClassA | string) { + this.field1 = field1; + this.field2 = field2; + } +} diff --git a/ark_guard/abckit_wrapper/tests/ut/file_view_test.cpp b/ark_guard/abckit_wrapper/tests/ut/file_view_test.cpp index 69fc930aaf898ce0f194e058135a4eb4dc9341ac..59eafcbdc84ee70b4ac0419ebc36367a843fc417 100644 --- a/ark_guard/abckit_wrapper/tests/ut/file_view_test.cpp +++ b/ark_guard/abckit_wrapper/tests/ut/file_view_test.cpp @@ -82,6 +82,53 @@ HWTEST_F(TestFileView, fileView_namespace_001, TestSize.Level0) ValidateModuleObject("Ns1.Ns2"); } +/** + * @tc.name: fileView_function_001 + * @tc.desc: test fileView get function of module and namespace + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_function_001, TestSize.Level0) +{ + ValidateModuleObject("foo1:i32;i32;void;"); + ValidateModuleObject("Ns1.foo2:i32;i32;void;"); +} + +/** + * @tc.name: fileView_function_002 + * @tc.desc: test fileView get function signature + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_function_002, TestSize.Level0) +{ + AssertSignatureEqual("foo1:i32;i32;void;", "foo1", "(i32, i32)void"); + AssertSignatureEqual("Ns1.foo2:i32;i32;void;", "foo2", "(i32, i32)void"); +} + +/** + * @tc.name: fileView_module_field_001 + * @tc.desc: test fileView get module field of module and namespace + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_module_field_001, TestSize.Level0) +{ + ValidateModuleObject("m1"); + ValidateModuleObject("Ns1.m2"); +} + +/** + * @tc.name: fileView_module_field_002 + * @tc.desc: test fileView get module field signature + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_module_field_002, TestSize.Level0) +{ + AssertSignatureEqual("m1", "m1", ""); + AssertSignatureEqual("Ns1.m2", "m2", ""); +} + /** * @tc.name: fileView_class_001 * @tc.desc: test fileView get class of module and namespace @@ -94,6 +141,80 @@ HWTEST_F(TestFileView, fileView_class_001, TestSize.Level0) ValidateModuleObject("Ns1.ClassB"); } +/** + * @tc.name: fileView_class_002 + * @tc.desc: test fileView get class methods of module and namespace + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_class_002, TestSize.Level0) +{ + ValidateModuleObject("ClassA.method1:module_static.ClassA;void;"); + ValidateModuleObject("ClassA.iField1:module_static.ClassA;i32;"); + ValidateModuleObject("ClassA.iField1:module_static.ClassA;i32;void;"); + + ValidateModuleObject("Ns1.ClassB.method2:module_static.Ns1.ClassB;void;"); + ValidateModuleObject("Ns1.ClassB.iField2:module_static.Ns1.ClassB;std.core.String;"); + ValidateModuleObject( + "Ns1.ClassB.iField2:module_static.Ns1.ClassB;std.core.String;void;"); +} + +/** + * @tc.name: fileView_class_003 + * @tc.desc: test fileView get class fields of module and namespace + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_class_003, TestSize.Level0) +{ + ValidateModuleObject("ClassA.sField1"); + ValidateModuleObject("ClassA.field1"); + ValidateModuleObject("ClassA.iField1"); + + ValidateModuleObject("Ns1.ClassB.sField2"); + ValidateModuleObject("Ns1.ClassB.field2"); + ValidateModuleObject("Ns1.ClassB.iField2"); +} + +/** + * @tc.name: fileView_class_004 + * @tc.desc: test fileView get class methods signature + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_class_004, TestSize.Level0) +{ + AssertSignatureEqual("ClassA.sMethod1:i32;void;", "sMethod1", "(i32)void"); + AssertSignatureEqual("ClassA.method1:module_static.ClassA;void;", "method1", "()void"); + AssertSignatureEqual("ClassA.iField1:module_static.ClassA;i32;", "iField1", ""); + AssertSignatureEqual("ClassA.iField1:module_static.ClassA;i32;void;", "iField1", ""); + + AssertSignatureEqual("Ns1.ClassB.sMethod2:i32;void;", "sMethod2", "(i32)void"); + AssertSignatureEqual("Ns1.ClassB.method2:module_static.Ns1.ClassB;void;", "method2", + "()void"); + AssertSignatureEqual("Ns1.ClassB.iField2:module_static.Ns1.ClassB;std.core.String;", + "iField2", ""); + AssertSignatureEqual( + "Ns1.ClassB.iField2:module_static.Ns1.ClassB;std.core.String;void;", "iField2", ""); +} + +/** + * @tc.name: fileView_class_005 + * @tc.desc: test fileView get class fields signature + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_class_005, TestSize.Level0) +{ + AssertSignatureEqual("ClassA.sField1", "sField1", ""); + AssertSignatureEqual("ClassA.field1", "field1", ""); + AssertSignatureEqual("ClassA.iField1", "iField1", ""); + + AssertSignatureEqual("Ns1.ClassB.sField2", "sField2", ""); + AssertSignatureEqual("Ns1.ClassB.field2", "field2", ""); + AssertSignatureEqual("Ns1.ClassB.iField2", "iField2", ""); +} + /** * @tc.name: fileView_interface_001 * @tc.desc: test fileView get interface of module and namespace @@ -106,6 +227,30 @@ HWTEST_F(TestFileView, fileView_interface_001, TestSize.Level0) ValidateModuleObject("Ns1.Interface2"); } +/** + * @tc.name: fileView_interface_002 + * @tc.desc: test fileView get interface methods of module and namespace + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_interface_002, TestSize.Level0) +{ + ValidateModuleObject("Interface1.iMethod1:module_static.Interface1;void;"); + ValidateModuleObject("Ns1.Interface2.iMethod2:module_static.Ns1.Interface2;void;"); +} + +/** + * @tc.name: fileView_interface_003 + * @tc.desc: test fileView get interface fields of module and namespace + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_interface_003, TestSize.Level0) +{ + ValidateModuleObject("Interface1.iField1"); + ValidateModuleObject("Ns1.Interface2.iField2"); +} + /** * @tc.name: fileView_enum_001 * @tc.desc: test fileView get enum of module and namespace @@ -116,4 +261,28 @@ HWTEST_F(TestFileView, fileView_enum_001, TestSize.Level0) { ValidateModuleObject("Color1"); ValidateModuleObject("Ns1.Color2"); +} + +/** + * @tc.name: fileView_enum_002 + * @tc.desc: test fileView get enum fields of module and namespace + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_enum_002, TestSize.Level0) +{ + ValidateModuleObject("Color1.RED"); + ValidateModuleObject("Ns1.Color2.YELLOW"); +} + +/** + * @tc.name: fileView_annotation_interface_001 + * @tc.desc: test fileView get annotationInterface of module and namespace + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestFileView, fileView_annotation_interface_001, TestSize.Level0) +{ + ValidateModuleObject("MyAnno1"); + ValidateModuleObject("Ns1.MyAnno2"); } \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/hierarchy_dumper_test.cpp b/ark_guard/abckit_wrapper/tests/ut/hierarchy_dumper_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8df0321b3b89c8ec43f48b9330fe91b7f47fbaa8 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/hierarchy_dumper_test.cpp @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "abckit_wrapper/hierarchy_dumper.h" +#include "test_util/assert.h" + +using namespace testing::ext; + +namespace { +constexpr std::string_view ABC_FILE_PATH = ABCKIT_WRAPPER_ABC_FILE_DIR "ut/module_static.abc"; +constexpr std::string_view DUMP_FILE_PATH = ABCKIT_WRAPPER_ABC_FILE_DIR "ut/hierarchy_dumper.txt"; +abckit_wrapper::FileView fileView; +} // namespace + +class TestHierarchyDumper : public testing::Test { +public: + static void SetUpTestSuite() + { + ASSERT_SUCCESS(fileView.Init(ABC_FILE_PATH)); + } +}; + +/** + * @tc.name: hierarchy_dump_001 + * @tc.desc: test dump hierarchy of the fileView + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestHierarchyDumper, hierarchy_dump_001, TestSize.Level4) +{ + abckit_wrapper::HierarchyDumper dumper(fileView, DUMP_FILE_PATH); + ASSERT_SUCCESS(dumper.Dump()); +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/logger_test.cpp b/ark_guard/abckit_wrapper/tests/ut/logger_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..81f58adf920913d41448322a8ae584e6cb167d90 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/logger_test.cpp @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "../../library/logger.h" + +using namespace testing::ext; + +/** + * @tc.name: logger_001 + * @tc.desc: test logger print + * @tc.type: FUNC + * @tc.require: + */ +HWTEST(abckit_wrapper, logger_001, TestSize.Level4) +{ + LOG_D << "debug"; + LOG_I << "info"; + LOG_W << "warn"; + LOG_E << "error"; +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/method_param_test.cpp b/ark_guard/abckit_wrapper/tests/ut/method_param_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9206f9c6553f8165504e58b0649f16817501eff --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/method_param_test.cpp @@ -0,0 +1,121 @@ +/** + * 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 "abckit_wrapper/file_view.h" +#include "test_util/assert.h" + +using namespace testing::ext; + +namespace { +constexpr std::string_view ABC_FILE_PATH = ABCKIT_WRAPPER_ABC_FILE_DIR "ut/method_param_test.abc"; +abckit_wrapper::FileView fileView; +} // namespace + +class TestBaseMethodParamVisitor : public abckit_wrapper::ParameterVisitor { +public: + virtual void InitTargetParameterTypeNames() = 0; + + void AddTargetParameterTypeName(const std::string &name) + { + this->targetParameterTypeNames_.emplace_back(name); + } + + bool Visit(abckit_wrapper::Parameter *parameter) override + { + this->parameters_.emplace_back(parameter); + return true; + } + + void Validate() + { + this->InitTargetParameterTypeNames(); + for (size_t i = 0; i < std::min(this->targetParameterTypeNames_.size(), this->parameters_.size()); ++i) { + ASSERT_EQ(this->targetParameterTypeNames_[i], this->parameters_[i]->GetTypeName()); + } + } + +private: + std::vector parameters_; + std::vector targetParameterTypeNames_; +}; + +class TestMethodParam : public ::testing::Test { +public: + static void SetUpTestSuite() + { + ASSERT_SUCCESS(fileView.Init(ABC_FILE_PATH)); + } + + void TearDown() override + { + ASSERT_TRUE(visitor_ != nullptr); + visitor_->Validate(); + } + +protected: + std::unique_ptr visitor_ = nullptr; +}; + +class TestClassMethodParamVisitor final : public TestBaseMethodParamVisitor { +public: + void InitTargetParameterTypeNames() override + { + AddTargetParameterTypeName("method_param_test.ClassA"); + AddTargetParameterTypeName("i32"); + AddTargetParameterTypeName("std.core.String"); + AddTargetParameterTypeName("escompat.Array"); + } +}; + +/** + * @tc.name: method_param_001 + * @tc.desc: test visit class method params + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestMethodParam, method_param_001, TestSize.Level0) +{ + const auto method1 = fileView.Get( + "method_param_test.ClassA.method1:method_param_test.ClassA;i32;std.core.String;escompat.Array;void;"); + ASSERT_TRUE(method1.has_value()); + visitor_ = std::make_unique(); + method1.value()->ParametersAccept(*visitor_); +} + +class TestFunctionParamVisitor final : public TestBaseMethodParamVisitor { +public: + void InitTargetParameterTypeNames() override + { + AddTargetParameterTypeName("i32"); + AddTargetParameterTypeName("method_param_test.ClassA"); + AddTargetParameterTypeName("std.core.String"); + AddTargetParameterTypeName("escompat.Array"); + } +}; + +/** + * @tc.name: method_param_002 + * @tc.desc: test visit function params + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestMethodParam, method_param_002, TestSize.Level0) +{ + const auto foo1 = fileView.Get( + "method_param_test.foo1:i32;method_param_test.ClassA;std.core.String;escompat.Array;void;"); + ASSERT_TRUE(foo1.has_value()); + visitor_ = std::make_unique(); + foo1.value()->ParametersAccept(*visitor_); +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/method_param_test.ets b/ark_guard/abckit_wrapper/tests/ut/method_param_test.ets new file mode 100644 index 0000000000000000000000000000000000000000..a6a708c8e9c870373b2057055286c6c77e3b8d34 --- /dev/null +++ b/ark_guard/abckit_wrapper/tests/ut/method_param_test.ets @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class ClassA { + public method1(a: int, b: string, c: Array) { + } +} + +function foo1(a: int, b: ClassA, c: string, d: Array) { +} \ No newline at end of file diff --git a/ark_guard/abckit_wrapper/tests/ut/module_static.ets b/ark_guard/abckit_wrapper/tests/ut/module_static.ets index f7542293491dea9474a465387ac54235fd2df8ce..4a6b9b9e15db9b2db51fb3fa36cb208b54e2e097 100644 --- a/ark_guard/abckit_wrapper/tests/ut/module_static.ets +++ b/ark_guard/abckit_wrapper/tests/ut/module_static.ets @@ -23,19 +23,25 @@ interface Interface1 { iMethod1(); } +@interface MyAnno1 {} + +@MyAnno1() class ClassA implements Interface1{ - public static sField1 = 0; + @MyAnno1() + static sField1 = 0; - public field1 = ''; - public iField1 = 0; + @MyAnno1() + field1 = ''; + iField1 = 0; - public static sMethod1(a: int){ + static sMethod1(a: int){ } - public method1() { + @MyAnno1() + method1() { } - public iMethod1() { + iMethod1() { } } @@ -58,19 +64,26 @@ namespace Ns1 { iMethod2(); } + @interface MyAnno2 {} + + @MyAnno1() + @MyAnno2() class ClassB implements Interface2{ - public static sField2 = 0; + @MyAnno2() + static sField2 = 0; - public field2 = ''; - public iField2 = ''; + @MyAnno2() + field2 = ''; + iField2 = ''; - public static sMethod2(a: int){ + static sMethod2(a: int){ } - public method2() { + @MyAnno2() + method2() { } - public iMethod2() { + iMethod2() { } } diff --git a/ark_guard/abckit_wrapper/tests/ut/visitor_test.cpp b/ark_guard/abckit_wrapper/tests/ut/visitor_test.cpp index dde1706983cdc26d574af5374224eee57bbfbef3..3c9fba5dbbd531e81d70d5171351615dd5ee7046 100644 --- a/ark_guard/abckit_wrapper/tests/ut/visitor_test.cpp +++ b/ark_guard/abckit_wrapper/tests/ut/visitor_test.cpp @@ -124,6 +124,137 @@ HWTEST_F(TestVisitor, namespace_visitor_001, TestSize.Level1) ASSERT_TRUE(fileView.ModulesAccept(visitor_->Wrap())); } +class TestMethodVisitor final : public BaseTestVisitor, public abckit_wrapper::MethodVisitor { +public: + void InitTargetObjectNames() override + { + AddTargetObjectName("module_static.Color1.valueOf:module_static.Color1;i32;"); + AddTargetObjectName("module_static.Ns1.Color2.getName:module_static.Ns1.Color2;std.core.String;"); + AddTargetObjectName("module_static.Color1.$_get:module_static.Color1;std.core.String;"); + AddTargetObjectName("module_static.Ns1.ClassB._ctor_:module_static.Ns1.ClassB;void;"); + AddTargetObjectName("module_static.Ns1.Color2.toString:module_static.Ns1.Color2;std.core.String;"); + AddTargetObjectName("module_static.Ns1.Color2._cctor_:void;"); + AddTargetObjectName("module_static.Ns1.Color2.valueOf:module_static.Ns1.Color2;i32;"); + AddTargetObjectName("module_static.Ns1.Color2._ctor_:module_static.Ns1.Color2;i32;i32;void;"); + AddTargetObjectName("module_static.Ns1.Interface2.iMethod2:module_static.Ns1.Interface2;void;"); + AddTargetObjectName("module_static.Color1._ctor_:module_static.Color1;i32;i32;void;"); + AddTargetObjectName("module_static.Ns1.Ns2._cctor_:void;"); + AddTargetObjectName("module_static.Ns1._cctor_:void;"); + AddTargetObjectName("module_static._cctor_:void;"); + AddTargetObjectName("module_static.Ns1.Color2.$_get:module_static.Ns1.Color2;std.core.String;"); + AddTargetObjectName("module_static.Ns1.ClassB._cctor_:void;"); + AddTargetObjectName("module_static.Ns1.ClassB.sMethod2:i32;void;"); + AddTargetObjectName("module_static.Ns1.ClassB.iField2:module_static.Ns1.ClassB;std.core.String;void;"); + AddTargetObjectName("module_static.Ns1.ClassB.iField2:module_static.Ns1.ClassB;std.core.String;"); + AddTargetObjectName("module_static.Ns1.ClassB.iMethod2:module_static.Ns1.ClassB;void;"); + AddTargetObjectName("module_static.ClassA._ctor_:module_static.ClassA;void;"); + AddTargetObjectName("module_static.ClassA.sMethod1:i32;void;"); + AddTargetObjectName("module_static.ClassA.iField1:module_static.ClassA;i32;void;"); + AddTargetObjectName("module_static.ClassA.iField1:module_static.ClassA;i32;"); + AddTargetObjectName("module_static.Color1.values:module_static.Color1[];"); + AddTargetObjectName("module_static.Color1.fromValue:i32;module_static.Color1;"); + AddTargetObjectName("module_static.Ns1.Color2.fromValue:i32;module_static.Ns1.Color2;"); + AddTargetObjectName("module_static.Ns1.foo2:i32;i32;void;"); + AddTargetObjectName("module_static.Ns1.Interface2.iField2:module_static.Ns1.Interface2;std.core.String;"); + AddTargetObjectName("module_static.Interface1.iMethod1:module_static.Interface1;void;"); + AddTargetObjectName("module_static.Color1.getValueOf:std.core.String;module_static.Color1;"); + AddTargetObjectName( + "module_static.Ns1.Interface2.iField2:module_static.Ns1.Interface2;std.core.String;void;"); + AddTargetObjectName("module_static.foo1:i32;i32;void;"); + AddTargetObjectName("module_static.main:void;"); + AddTargetObjectName("module_static.Ns1.ClassB.method2:module_static.Ns1.ClassB;void;"); + AddTargetObjectName("module_static.ClassA._cctor_:void;"); + AddTargetObjectName("module_static.ClassA.iMethod1:module_static.ClassA;void;"); + AddTargetObjectName("module_static.Ns1.Color2.getOrdinal:module_static.Ns1.Color2;i32;"); + AddTargetObjectName("module_static.ClassA.method1:module_static.ClassA;void;"); + AddTargetObjectName("module_static.Ns1.Color2.getValueOf:std.core.String;module_static.Ns1.Color2;"); + AddTargetObjectName("module_static.Color1.getOrdinal:module_static.Color1;i32;"); + AddTargetObjectName("module_static.Ns1.Color2.values:module_static.Ns1.Color2[];"); + AddTargetObjectName("module_static.Color1.toString:module_static.Color1;std.core.String;"); + AddTargetObjectName("module_static.Interface1.iField1:module_static.Interface1;i32;"); + AddTargetObjectName("module_static.Interface1.iField1:module_static.Interface1;i32;void;"); + AddTargetObjectName("module_static.Color1._cctor_:void;"); + AddTargetObjectName("module_static.Color1.getName:module_static.Color1;std.core.String;"); + } + + bool Visit(abckit_wrapper::Module *module) override + { + return module->MethodsAccept(*this); + } + + bool Visit(abckit_wrapper::Method *method) override + { + LOG_I << "MethodName:" << method->GetFullyQualifiedName(); + objects_.push_back(method); + return true; + } +}; + +/** + * @tc.name: method_visitor_001 + * @tc.desc: test visit all methods(functions & methods) of the fileView + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestVisitor, method_visitor_001, TestSize.Level1) +{ + visitor_ = std::make_unique(); + ASSERT_TRUE(fileView.ModulesAccept(*visitor_)); +} + +class TestFieldVisitor final : public BaseTestVisitor, public abckit_wrapper::FieldVisitor { +public: + void InitTargetObjectNames() override + { + AddTargetObjectName("module_static.Color1._StringValuesArray"); + AddTargetObjectName("module_static.Color1._ValuesArray"); + AddTargetObjectName("module_static.Color1.RED"); + AddTargetObjectName("module_static.Ns1.Color2.YELLOW"); + AddTargetObjectName("module_static.Color1._NamesArray"); + AddTargetObjectName("module_static.Ns1.m2"); + AddTargetObjectName("module_static.Ns1.Color2._ordinal"); + AddTargetObjectName("module_static.Ns1.Color2._StringValuesArray"); + AddTargetObjectName("module_static.Ns1.ClassB.sField2"); + AddTargetObjectName("module_static.Ns1.ClassB.iField2"); + AddTargetObjectName("module_static.Interface1.iField1"); + AddTargetObjectName("module_static.Color1._ordinal"); + AddTargetObjectName("module_static.Ns1.Color2._NamesArray"); + AddTargetObjectName("module_static.Ns1.ClassB.field2"); + AddTargetObjectName("module_static.Ns1.Color2._ItemsArray"); + AddTargetObjectName("module_static.Color1._ItemsArray"); + AddTargetObjectName("module_static.m1"); + AddTargetObjectName("module_static.ClassA.field1"); + AddTargetObjectName("module_static.ClassA.iField1"); + AddTargetObjectName("module_static.Ns1.Interface2.iField2"); + AddTargetObjectName("module_static.ClassA.sField1"); + AddTargetObjectName("module_static.Ns1.Color2._ValuesArray"); + } + + bool Visit(abckit_wrapper::Module *module) override + { + return module->FieldsAccept(*this); + } + + bool Visit(abckit_wrapper::Field *field) override + { + LOG_I << "FieldName:" << field->GetFullyQualifiedName(); + objects_.push_back(field); + return true; + } +}; + +/** + * @tc.name: field_visitor_001 + * @tc.desc: test visit all fields of the fileView + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestVisitor, field_visitor_001, TestSize.Level1) +{ + visitor_ = std::make_unique(); + ASSERT_TRUE(fileView.ModulesAccept(*visitor_)); +} + class TestLocalClassVisitor final : public BaseTestVisitor, public abckit_wrapper::ClassVisitor { public: void InitTargetObjectNames() override @@ -204,17 +335,59 @@ HWTEST_F(TestVisitor, class_visitor_002, TestSize.Level1) visitor_ = std::move(testVisitor); } +class TestLocalAnnotationInterfaceVisitor final : public BaseTestVisitor, + public abckit_wrapper::AnnotationInterfaceVisitor { +public: + void InitTargetObjectNames() override + { + AddTargetObjectName("module_static.MyAnno1"); + AddTargetObjectName("module_static.Ns1.MyAnno2"); + } + + bool Visit(abckit_wrapper::Module *module) override + { + return module->AnnotationInterfacesAccept(*this); + } + + bool Visit(abckit_wrapper::AnnotationInterface *ai) override + { + LOG_I << "AnnotationInterfaceName:" << ai->GetFullyQualifiedName(); + objects_.push_back(ai); + return true; + } +}; + +/** + * @tc.name: annotation_interface_visitor_001 + * @tc.desc: test visit all local annotationInterface of the fileView + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestVisitor, annotation_interface_visitor_001, TestSize.Level1) +{ + visitor_ = std::make_unique(); + ASSERT_TRUE(fileView.ModulesAccept(visitor_->Wrap())); +} + class TestLocalModuleChildVisitor final : public BaseTestVisitor, public abckit_wrapper::ChildVisitor { public: void InitTargetObjectNames() override { // Namespaces AddTargetObjectName("module_static.Ns1"); + // Functions + AddTargetObjectName("module_static.main:void;"); + AddTargetObjectName("module_static.foo1:i32;i32;void;"); + AddTargetObjectName("module_static._cctor_:void;"); + // Fields + AddTargetObjectName("module_static.m1"); // Classes AddTargetObjectName("module_static.ClassA"); AddTargetObjectName("module_static.Color1"); AddTargetObjectName("module_static.Color1[]"); AddTargetObjectName("module_static.Interface1"); + // AnnotationInterfaces + AddTargetObjectName("module_static.MyAnno1"); } bool Visit(abckit_wrapper::Module *module) override @@ -229,12 +402,33 @@ public: return true; } + bool VisitMethod(abckit_wrapper::Method *method) override + { + LOG_I << "MethodName:" << method->GetFullyQualifiedName(); + objects_.push_back(method); + return true; + } + + bool VisitField(abckit_wrapper::Field *field) override + { + LOG_I << "FieldName:" << field->GetFullyQualifiedName(); + objects_.push_back(field); + return true; + } + bool VisitClass(abckit_wrapper::Class *clazz) override { LOG_I << "ClassName:" << clazz->GetFullyQualifiedName(); objects_.push_back(clazz); return true; } + + bool VisitAnnotationInterface(abckit_wrapper::AnnotationInterface *ai) override + { + LOG_I << "AnnotationInterfaceName:" << ai->GetFullyQualifiedName(); + objects_.push_back(ai); + return true; + } }; /** @@ -255,11 +449,18 @@ public: { // Namespaces AddTargetObjectName("module_static.Ns1.Ns2"); + // Functions + AddTargetObjectName("module_static.Ns1._cctor_:void;"); + AddTargetObjectName("module_static.Ns1.foo2:i32;i32;void;"); + // Fields + AddTargetObjectName("module_static.Ns1.m2"); // Classes AddTargetObjectName("module_static.Ns1.ClassB"); AddTargetObjectName("module_static.Ns1.Color2"); AddTargetObjectName("module_static.Ns1.Color2[]"); AddTargetObjectName("module_static.Ns1.Interface2"); + // AnnotationInterfaces + AddTargetObjectName("module_static.Ns1.MyAnno2"); } bool Visit(abckit_wrapper::Module *module) override @@ -274,12 +475,33 @@ public: return true; } + bool VisitMethod(abckit_wrapper::Method *method) override + { + LOG_I << "MethodName:" << method->GetFullyQualifiedName(); + objects_.push_back(method); + return true; + } + + bool VisitField(abckit_wrapper::Field *field) override + { + LOG_I << "FieldName:" << field->GetFullyQualifiedName(); + objects_.push_back(field); + return true; + } + bool VisitClass(abckit_wrapper::Class *clazz) override { LOG_I << "ClassName:" << clazz->GetFullyQualifiedName(); objects_.push_back(clazz); return true; } + + bool VisitAnnotationInterface(abckit_wrapper::AnnotationInterface *ai) override + { + LOG_I << "AnnotationInterfaceName:" << ai->GetFullyQualifiedName(); + objects_.push_back(ai); + return true; + } }; /** @@ -297,6 +519,90 @@ HWTEST_F(TestVisitor, child_visitor_002, TestSize.Level1) visitor_ = std::move(testVisitor); } +class TestLocalClassChildVisitor final : public BaseTestVisitor, public abckit_wrapper::ChildVisitor { +public: + void InitTargetObjectNames() override + { + // Methods + AddTargetObjectName("module_static.ClassA.sMethod1:i32;void;"); + AddTargetObjectName("module_static.ClassA.method1:module_static.ClassA;void;"); + AddTargetObjectName("module_static.ClassA._ctor_:module_static.ClassA;void;"); + AddTargetObjectName("module_static.ClassA._cctor_:void;"); + AddTargetObjectName("module_static.ClassA.iField1:module_static.ClassA;i32;void;"); + AddTargetObjectName("module_static.ClassA.iField1:module_static.ClassA;i32;"); + AddTargetObjectName("module_static.ClassA.iMethod1:module_static.ClassA;void;"); + // Fields + AddTargetObjectName("module_static.ClassA.field1"); + AddTargetObjectName("module_static.ClassA.sField1"); + AddTargetObjectName("module_static.ClassA.iField1"); + } + + bool Visit(abckit_wrapper::Module *module) override + { + return true; + } + + bool VisitMethod(abckit_wrapper::Method *method) override + { + LOG_I << "MethodName:" << method->GetFullyQualifiedName(); + objects_.push_back(method); + return true; + } + + bool VisitField(abckit_wrapper::Field *field) override + { + LOG_I << "FieldName:" << field->GetFullyQualifiedName(); + objects_.push_back(field); + return true; + } +}; + +/** + * @tc.name: child_visitor_003 + * @tc.desc: test visit all directly child of the local class + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestVisitor, child_visitor_003, TestSize.Level1) +{ + auto testVisitor = std::make_unique(); + const auto clazz = fileView.Get("module_static.ClassA"); + ASSERT_TRUE(clazz.has_value()); + ASSERT_TRUE(clazz.value()->ChildrenAccept(*testVisitor)); + visitor_ = std::move(testVisitor); +} + +class TestClassAMemberVisitor final : public BaseTestVisitor, public abckit_wrapper::MemberVisitor { +public: + void InitTargetObjectNames() override + { + // Methods + AddTargetObjectName("module_static.ClassA.sMethod1:i32;void;"); + AddTargetObjectName("module_static.ClassA.method1:module_static.ClassA;void;"); + AddTargetObjectName("module_static.ClassA._ctor_:module_static.ClassA;void;"); + AddTargetObjectName("module_static.ClassA._cctor_:void;"); + AddTargetObjectName("module_static.ClassA.iField1:module_static.ClassA;i32;void;"); + AddTargetObjectName("module_static.ClassA.iField1:module_static.ClassA;i32;"); + AddTargetObjectName("module_static.ClassA.iMethod1:module_static.ClassA;void;"); + // Fields + AddTargetObjectName("module_static.ClassA.field1"); + AddTargetObjectName("module_static.ClassA.sField1"); + AddTargetObjectName("module_static.ClassA.iField1"); + } + + bool Visit(abckit_wrapper::Module *module) override + { + return true; + } + + bool Visit(abckit_wrapper::Member *member) override + { + LOG_I << "MemberName:" << member->GetFullyQualifiedName(); + objects_.emplace_back(member); + return true; + } +}; + class TestClassAFilter final : public abckit_wrapper::ClassFilter { public: explicit TestClassAFilter(ClassVisitor &visitor) : ClassFilter(visitor) {} @@ -306,3 +612,19 @@ public: return clazz->GetFullyQualifiedName() == "module_static.ClassA"; } }; + +/** + * @tc.name: member_visitor_001 + * @tc.desc: test visit all directly child of the local class + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(TestVisitor, member_visitor_001, TestSize.Level1) +{ + auto testVisitor = std::make_unique(); + abckit_wrapper::MemberVisitor *memberVisitor = testVisitor.get(); + fileView.ModulesAccept(memberVisitor->Wrap() + .Wrap() + .Wrap()); + visitor_ = std::move(testVisitor); +} \ No newline at end of file diff --git a/libabckit/src/adapter_static/metadata_inspect_static.cpp b/libabckit/src/adapter_static/metadata_inspect_static.cpp index f2c72af6dfb4fa230498f516cc3f94b3432cfcbf..2b904094e6dbb7271f7619b3a177e55fe717ccc3 100644 --- a/libabckit/src/adapter_static/metadata_inspect_static.cpp +++ b/libabckit/src/adapter_static/metadata_inspect_static.cpp @@ -83,6 +83,12 @@ AbckitString *NamespaceGetNameStatic(AbckitCoreNamespace *ns) return CreateStringStatic(ns->owningModule->file, namespaceName.data(), namespaceName.size()); } +bool NamespaceIsExternalStatic(AbckitCoreNamespace *ns) +{ + LIBABCKIT_LOG_FUNC; + return ns->GetArkTSImpl()->impl.GetStaticClass()->metadata->IsForeign(); +} + // ======================================== // Class // ======================================== diff --git a/libabckit/src/adapter_static/metadata_inspect_static.h b/libabckit/src/adapter_static/metadata_inspect_static.h index 17e14c802061c861c6f6129fe922728f47b0824e..d2ce40a463076280dc67549eff8c33a79701cc71 100644 --- a/libabckit/src/adapter_static/metadata_inspect_static.h +++ b/libabckit/src/adapter_static/metadata_inspect_static.h @@ -33,6 +33,8 @@ bool ModuleEnumerateAnonymousFunctionsStatic(AbckitCoreModule *m, void *data, AbckitString *NamespaceGetNameStatic(AbckitCoreNamespace *ns); +bool NamespaceIsExternalStatic(AbckitCoreNamespace *ns); + // ======================================== // Class // ======================================== diff --git a/libabckit/src/helpers_common.cpp b/libabckit/src/helpers_common.cpp index b00326ed199166cc8475a1955fadc0d650eb4682..cb7fde1d37c746cc435112260b7554e85dc02fd4 100644 --- a/libabckit/src/helpers_common.cpp +++ b/libabckit/src/helpers_common.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 @@ -191,6 +191,20 @@ bool NamespaceEnumerateFieldsHelper(AbckitCoreNamespace *n, void *data, return true; } +bool NamespaceEnumerateAnnotationInterfacesHelper(AbckitCoreNamespace *n, void *data, + bool (*cb)(AbckitCoreAnnotationInterface *ai, void *data)) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(n, false) + LIBABCKIT_BAD_ARGUMENT(cb, false) + for (auto &[atName, at] : n->at) { + if (!cb(at.get(), data)) { + return false; + } + } + return true; +} + bool ClassEnumerateMethodsHelper(AbckitCoreClass *klass, void *data, bool (*cb)(AbckitCoreFunction *method, void *data)) { LIBABCKIT_LOG_FUNC; diff --git a/libabckit/src/helpers_common.h b/libabckit/src/helpers_common.h index 9bf49be0ab2f7603cdf627f00d304fe7c44cad48..b82f09f5c368a82aa4a83ce58bfb0e2dd35eec57 100644 --- a/libabckit/src/helpers_common.h +++ b/libabckit/src/helpers_common.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 @@ -42,6 +42,8 @@ bool NamespaceEnumerateTopLevelFunctionsHelper(AbckitCoreNamespace *n, void *dat bool (*cb)(AbckitCoreFunction *function, void *data)); bool NamespaceEnumerateFieldsHelper(AbckitCoreNamespace *n, void *data, bool (*cb)(AbckitCoreNamespaceField *field, void *data)); +bool NamespaceEnumerateAnnotationInterfacesHelper(AbckitCoreNamespace *n, void *data, + bool (*cb)(AbckitCoreAnnotationInterface *ai, void *data)); bool ClassEnumerateMethodsHelper(AbckitCoreClass *klass, void *data, bool (*cb)(AbckitCoreFunction *method, void *data)); diff --git a/libabckit/src/metadata_arkts_inspect_impl.cpp b/libabckit/src/metadata_arkts_inspect_impl.cpp index 3a4022b707fac7913f030a64499da7b296ef6553..6d5463d72fa0825037129d3de05b0bb438adcae0 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 @@ -776,6 +776,12 @@ bool ArkTSNamespaceEnumerateTopLevelFunctions(AbckitCoreNamespace *n, void *data return true; } +bool ArkTSNamespaceEnumerateAnnotationInterfaces(AbckitCoreNamespace *n, void *data, + bool (*cb)(AbckitCoreAnnotationInterface *ai, void *data)) +{ + return NamespaceEnumerateAnnotationInterfacesHelper(n, data, cb); +} + // ======================================== // Class // ======================================== diff --git a/libabckit/src/metadata_arkts_inspect_impl.h b/libabckit/src/metadata_arkts_inspect_impl.h index c064b6f8b6594bb26382fa7abe3a7ec6f8e5e7bb..3ad0c31ca0547319f45babac7a78c4f825d0d77e 100644 --- a/libabckit/src/metadata_arkts_inspect_impl.h +++ b/libabckit/src/metadata_arkts_inspect_impl.h @@ -55,6 +55,8 @@ bool ArkTSNamespaceEnumerateFields(AbckitCoreNamespace *n, void *data, bool (*cb)(AbckitCoreNamespaceField *field, void *data)); bool ArkTSNamespaceEnumerateTopLevelFunctions(AbckitCoreNamespace *n, void *data, bool (*cb)(AbckitCoreFunction *func, void *data)); +bool ArkTSNamespaceEnumerateAnnotationInterfaces(AbckitCoreNamespace *n, void *data, + bool (*cb)(AbckitCoreAnnotationInterface *ai, void *data)); // ======================================== // Class diff --git a/libabckit/src/metadata_inspect_impl.cpp b/libabckit/src/metadata_inspect_impl.cpp index f9b42e72716ee66beed2e8a2a492daa12d5910bb..c71e5d72c3cfc08fba5cf76deadfaf3ca7c8d848 100644 --- a/libabckit/src/metadata_inspect_impl.cpp +++ b/libabckit/src/metadata_inspect_impl.cpp @@ -362,9 +362,17 @@ extern "C" AbckitString *NamespaceGetName(AbckitCoreNamespace *n) extern "C" bool NamespaceIsExternal(AbckitCoreNamespace *ns) { - LIBABCKIT_UNIMPLEMENTED; - (void)ns; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + LIBABCKIT_BAD_ARGUMENT(ns, false); + + if (IsDynamic(ns->owningModule->target)) { + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + } + + return NamespaceIsExternalStatic(ns); } extern "C" AbckitCoreNamespace *NamespaceGetParentNamespace(AbckitCoreNamespace *n) @@ -498,11 +506,21 @@ extern "C" bool NamespaceEnumerateTopLevelFunctions(AbckitCoreNamespace *n, void extern "C" bool NamespaceEnumerateAnnotationInterfaces(AbckitCoreNamespace *n, void *data, bool (*cb)(AbckitCoreAnnotationInterface *ai, void *data)) { - LIBABCKIT_UNIMPLEMENTED; - (void)n; - (void)data; - (void)cb; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + LIBABCKIT_BAD_ARGUMENT(n, false) + LIBABCKIT_BAD_ARGUMENT(cb, false) + switch (ModuleGetTarget(n->owningModule)) { + case ABCKIT_TARGET_ARK_TS_V1: + case ABCKIT_TARGET_ARK_TS_V2: + return ArkTSNamespaceEnumerateAnnotationInterfaces(n, data, cb); + case ABCKIT_TARGET_JS: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + default: + LIBABCKIT_UNREACHABLE; + } } // ======================================== @@ -1441,9 +1459,13 @@ extern "C" AbckitCoreModule *AnnotationInterfaceGetModule(AbckitCoreAnnotationIn extern "C" AbckitCoreNamespace *AnnotationInterfaceGetParentNamespace(AbckitCoreAnnotationInterface *anno) { - LIBABCKIT_UNIMPLEMENTED; - (void)anno; - return nullptr; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(anno, nullptr); + + return anno->parentNamespace; } extern "C" AbckitString *AnnotationInterfaceGetName(AbckitCoreAnnotationInterface *ai)