From 5f799cc65d9a779a6ad7b507ac82395726d26655 Mon Sep 17 00:00:00 2001 From: Martchus Date: Sun, 24 Dec 2017 02:02:40 +0100 Subject: [PATCH] Prevent code generator for records which are only included --- generator/codegenerator.cpp | 22 ++++++++++++++++++++ generator/codegenerator.h | 5 +++++ generator/jsonserializationcodegenerator.cpp | 8 +++++++ generator/jsonserializationcodegenerator.h | 12 +++++------ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/generator/codegenerator.cpp b/generator/codegenerator.cpp index 808d470..c4a9563 100644 --- a/generator/codegenerator.cpp +++ b/generator/codegenerator.cpp @@ -1,8 +1,10 @@ #include "./codegenerator.h" +#include "./codefactory.h" #include #include +#include using namespace std; @@ -20,6 +22,26 @@ void CodeGenerator::addDeclaration(clang::Decl *decl) VAR_UNUSED(decl) } +/*! + * \brief Lazy initializes the source manager. + * \remarks This method must be called in generate() when subclassing to make use of isOnlyIncluded(). + */ +void CodeGenerator::lazyInitializeSourceManager() const +{ + if (factory().compilerInstance()) { + const_cast(this)->m_sourceManager = &factory().compilerInstance()->getSourceManager(); + } +} + +/*! + * \brief Returns whether the specified \a declaration is only included and not part of the actual file. + */ +bool CodeGenerator::isOnlyIncluded(const clang::Decl *declaration) const +{ + return m_sourceManager + && m_sourceManager->getFileID(m_sourceManager->getExpansionLoc(declaration->getSourceRange().getBegin())) != m_sourceManager->getMainFileID(); +} + /*! * \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 28686aa..c8c3490 100644 --- a/generator/codegenerator.h +++ b/generator/codegenerator.h @@ -8,6 +8,7 @@ namespace clang { class Decl; class CXXRecordDecl; +class SourceManager; } // namespace clang namespace ReflectiveRapidJSON { @@ -29,14 +30,18 @@ public: protected: CodeFactory &factory() const; + void lazyInitializeSourceManager() const; + bool isOnlyIncluded(const clang::Decl *declaration) const; static bool inheritsFromInstantiationOf(clang::CXXRecordDecl *record, const char *templateClass); private: CodeFactory &m_factory; + const clang::SourceManager *m_sourceManager; }; inline CodeGenerator::CodeGenerator(CodeFactory &factory) : m_factory(factory) + , m_sourceManager(nullptr) { } diff --git a/generator/jsonserializationcodegenerator.cpp b/generator/jsonserializationcodegenerator.cpp index 0132d4c..a0b84b5 100644 --- a/generator/jsonserializationcodegenerator.cpp +++ b/generator/jsonserializationcodegenerator.cpp @@ -73,6 +73,11 @@ void JsonSerializationCodeGenerator::addDeclaration(clang::Decl *decl) */ string JsonSerializationCodeGenerator::qualifiedNameIfRelevant(clang::CXXRecordDecl *record) const { + // skip all classes which are only included + if (isOnlyIncluded(record)) { + return string(); + } + // consider all classes inheriting from an instantiation of "JsonSerializable" relevant if (inheritsFromInstantiationOf(record, JsonSerializable::qualifiedName)) { return record->getQualifiedNameAsString(); @@ -143,6 +148,9 @@ ostream &operator<<(ostream &os, llvm::StringRef str) */ void JsonSerializationCodeGenerator::generate(ostream &os) const { + // initialize source manager to make use of isOnlyIncluded() for skipping records which are only included + lazyInitializeSourceManager(); + // find relevant classes const auto relevantClasses = findRelevantClasses(); if (relevantClasses.empty()) { diff --git a/generator/jsonserializationcodegenerator.h b/generator/jsonserializationcodegenerator.h index 227d3eb..2e1717d 100644 --- a/generator/jsonserializationcodegenerator.h +++ b/generator/jsonserializationcodegenerator.h @@ -46,18 +46,18 @@ private: const Options &m_options; }; -inline void JsonSerializationCodeGenerator::Options::appendTo(ApplicationUtilities::Argument *arg) -{ - arg->addSubArgument(&additionalClassesArg); - arg->addSubArgument(&visibilityArg); -} - inline JsonSerializationCodeGenerator::JsonSerializationCodeGenerator(CodeFactory &factory, const Options &options) : CodeGenerator(factory) , m_options(options) { } +inline void JsonSerializationCodeGenerator::Options::appendTo(ApplicationUtilities::Argument *arg) +{ + arg->addSubArgument(&additionalClassesArg); + arg->addSubArgument(&visibilityArg); +} + inline JsonSerializationCodeGenerator::RelevantClass::RelevantClass(std::string &&qualifiedName, clang::CXXRecordDecl *record) : qualifiedName(qualifiedName) , record(record)