Prevent code generator for records which are only included

This commit is contained in:
Martchus 2017-12-24 02:02:40 +01:00
parent bae7cf3414
commit 5f799cc65d
4 changed files with 41 additions and 6 deletions

View File

@ -1,8 +1,10 @@
#include "./codegenerator.h" #include "./codegenerator.h"
#include "./codefactory.h"
#include <c++utilities/application/global.h> #include <c++utilities/application/global.h>
#include <clang/AST/DeclCXX.h> #include <clang/AST/DeclCXX.h>
#include <clang/Frontend/CompilerInstance.h>
using namespace std; using namespace std;
@ -20,6 +22,26 @@ void CodeGenerator::addDeclaration(clang::Decl *decl)
VAR_UNUSED(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<CodeGenerator *>(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. * \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). * \remarks The specified \a record must be defined (not only forward-declared).

View File

@ -8,6 +8,7 @@
namespace clang { namespace clang {
class Decl; class Decl;
class CXXRecordDecl; class CXXRecordDecl;
class SourceManager;
} // namespace clang } // namespace clang
namespace ReflectiveRapidJSON { namespace ReflectiveRapidJSON {
@ -29,14 +30,18 @@ public:
protected: protected:
CodeFactory &factory() const; CodeFactory &factory() const;
void lazyInitializeSourceManager() const;
bool isOnlyIncluded(const clang::Decl *declaration) const;
static bool inheritsFromInstantiationOf(clang::CXXRecordDecl *record, const char *templateClass); static bool inheritsFromInstantiationOf(clang::CXXRecordDecl *record, const char *templateClass);
private: private:
CodeFactory &m_factory; CodeFactory &m_factory;
const clang::SourceManager *m_sourceManager;
}; };
inline CodeGenerator::CodeGenerator(CodeFactory &factory) inline CodeGenerator::CodeGenerator(CodeFactory &factory)
: m_factory(factory) : m_factory(factory)
, m_sourceManager(nullptr)
{ {
} }

View File

@ -73,6 +73,11 @@ void JsonSerializationCodeGenerator::addDeclaration(clang::Decl *decl)
*/ */
string JsonSerializationCodeGenerator::qualifiedNameIfRelevant(clang::CXXRecordDecl *record) const 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 // consider all classes inheriting from an instantiation of "JsonSerializable" relevant
if (inheritsFromInstantiationOf(record, JsonSerializable<void>::qualifiedName)) { if (inheritsFromInstantiationOf(record, JsonSerializable<void>::qualifiedName)) {
return record->getQualifiedNameAsString(); return record->getQualifiedNameAsString();
@ -143,6 +148,9 @@ ostream &operator<<(ostream &os, llvm::StringRef str)
*/ */
void JsonSerializationCodeGenerator::generate(ostream &os) const 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 // find relevant classes
const auto relevantClasses = findRelevantClasses(); const auto relevantClasses = findRelevantClasses();
if (relevantClasses.empty()) { if (relevantClasses.empty()) {

View File

@ -46,18 +46,18 @@ private:
const Options &m_options; 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) inline JsonSerializationCodeGenerator::JsonSerializationCodeGenerator(CodeFactory &factory, const Options &options)
: CodeGenerator(factory) : CodeGenerator(factory)
, m_options(options) , 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) inline JsonSerializationCodeGenerator::RelevantClass::RelevantClass(std::string &&qualifiedName, clang::CXXRecordDecl *record)
: qualifiedName(qualifiedName) : qualifiedName(qualifiedName)
, record(record) , record(record)