diff --git a/generator/binaryserializationcodegenerator.cpp b/generator/binaryserializationcodegenerator.cpp index a527104..0ce5c1b 100644 --- a/generator/binaryserializationcodegenerator.cpp +++ b/generator/binaryserializationcodegenerator.cpp @@ -127,6 +127,9 @@ void BinarySerializationCodeGenerator::generate(ostream &os) const os << " // write members\n"; auto membersWritten = false; for (const clang::FieldDecl *field : relevantClass.record->fields()) { + for (const auto &attr : field->getAttrs()) { + cout << " // annotation: " << readAnnotation(attr) << '\n'; + } if (writePrivateMembers || field->getAccess() == clang::AS_public) { os << " serializer.write(customObject." << field->getName() << ");\n"; membersWritten = true; diff --git a/generator/codegenerator.cpp b/generator/codegenerator.cpp index 0694ae6..5ef257d 100644 --- a/generator/codegenerator.cpp +++ b/generator/codegenerator.cpp @@ -3,8 +3,10 @@ #include +#include #include #include +#include using namespace std; @@ -24,7 +26,7 @@ void CodeGenerator::addDeclaration(clang::Decl *decl) /*! * \brief Lazy initializes the source manager. - * \remarks This method must be called in generate() when subclassing to make use of isOnlyIncluded(). + * \remarks This method must be called in generate() when subclassing to make use of isOnlyIncluded() and readAnnotation(). */ void CodeGenerator::lazyInitializeSourceManager() const { @@ -42,6 +44,21 @@ bool CodeGenerator::isOnlyIncluded(const clang::Decl *declaration) const && m_sourceManager->getFileID(m_sourceManager->getExpansionLoc(declaration->getSourceRange().getBegin())) != m_sourceManager->getMainFileID(); } +/*! + * \brief Returns the specified \a annotation's text. + */ +std::string_view CodeGenerator::readAnnotation(const clang::Attr *annotation) const +{ + if (!m_sourceManager) { + return std::string_view(); + } + auto text = clang::Lexer::getSourceText(clang::CharSourceRange::getTokenRange(annotation->getRange()), *sourceManager(), clang::LangOptions()); + if (text.size() >= 12 && text.startswith("annotate(\"") && text.endswith("\")")) { + text = text.substr(10, text.size() - 12); + } + return text; +} + /*! * \brief Returns whether the specified \a record inherits from an instantiation of the specified \a templateClass. * \remarks The specified \a record must be defined (not only forward-declared). diff --git a/generator/codegenerator.h b/generator/codegenerator.h index 0c5de9d..6ceeed9 100644 --- a/generator/codegenerator.h +++ b/generator/codegenerator.h @@ -6,6 +6,7 @@ #include namespace clang { +class Attr; class Decl; class CXXRecordDecl; class SourceManager; @@ -32,6 +33,8 @@ protected: CodeFactory &factory() const; void lazyInitializeSourceManager() const; bool isOnlyIncluded(const clang::Decl *declaration) const; + std::string_view readAnnotation(const clang::Attr *annotation) const; + const clang::SourceManager *sourceManager() const; static bool inheritsFromInstantiationOf(clang::CXXRecordDecl *record, const char *templateClass); private: @@ -50,6 +53,11 @@ inline CodeFactory &CodeGenerator::factory() const return m_factory; } +inline const clang::SourceManager *CodeGenerator::sourceManager() const +{ + return m_sourceManager; +} + } // namespace ReflectiveRapidJSON #endif // REFLECTIVE_RAPIDJSON_CODE_GENERATOR_H diff --git a/generator/tests/morestructs.h b/generator/tests/morestructs.h index d355236..489e96b 100644 --- a/generator/tests/morestructs.h +++ b/generator/tests/morestructs.h @@ -67,4 +67,9 @@ struct PointerStruct : public BinarySerializable { std::shared_ptr s3; }; +struct AnnotatedStruct : public BinarySerializable { + int anyVersion; + __attribute__((annotate("cond:version >= 1"))) __attribute__((annotate("foo"))) int newInVersion1; +}; + #endif // REFLECTIVE_RAPIDJSON_TESTS_MORE_STRUCTS_H