Reflection for RapidJSON
0.0.17
Reflection for serializing/deserializing with RapidJSON
Toggle main menu visibility
Loading...
Searching...
No Matches
serializationcodegenerator.cpp
Go to the documentation of this file.
1
#include "
./serializationcodegenerator.h
"
2
3
#include <c++utilities/application/global.h>
4
5
#include <clang/AST/DeclCXX.h>
6
#include <clang/AST/DeclFriend.h>
7
#include <clang/AST/DeclTemplate.h>
8
#include <clang/AST/PrettyPrinter.h>
9
#include <clang/AST/QualTypeNames.h>
10
11
#include <iostream>
12
13
using namespace
std;
14
15
namespace
ReflectiveRapidJSON
{
16
20
ostream &
operator<<
(ostream &os, llvm::StringRef str)
21
{
22
return
os.write(str.data(),
static_cast<
streamsize
>
(str.size()));
23
}
24
29
void
SerializationCodeGenerator::addDeclaration
(clang::Decl *decl)
30
{
31
switch
(decl->getKind()) {
32
case
clang::Decl::Kind::CXXRecord:
33
case
clang::Decl::Kind::ClassTemplateSpecialization: {
34
auto
*
const
record =
static_cast<
clang::CXXRecordDecl *
>
(decl);
35
// skip forward declarations
36
if
(!record->hasDefinition()) {
37
return
;
38
}
39
40
// check for template specializations to adapt a 3rd party class/struct
41
if
(
m_qualifiedNameOfAdaptionRecords
&& decl->getKind() == clang::Decl::Kind::ClassTemplateSpecialization) {
42
auto
*
const
templateSpecializationRecord =
static_cast<
clang::ClassTemplateSpecializationDecl *
>
(decl);
43
// check whether the name of the template specialization matches
44
if
(templateSpecializationRecord->getQualifiedNameAsString() ==
m_qualifiedNameOfAdaptionRecords
) {
45
// get the template argument of the template specialization (exactly one argument expected)
46
const
auto
&templateArgs = templateSpecializationRecord->getTemplateArgs();
47
if
(templateArgs.size() != 1 || templateArgs.get(0).getKind() != clang::TemplateArgument::Type) {
48
return
;
// FIXME: use Clang diagnostics to print warning
49
}
50
// get the type the template argument refers to (that's the type of the 3rd party class/struct to adapt)
51
auto
*
const
templateRecord = templateArgs.get(0).getAsType()->getAsCXXRecordDecl();
52
if
(!templateRecord) {
53
return
;
// FIXME: use Clang diagnostics to print warning
54
}
55
// save the relevant information for the code generation
56
m_adaptionRecords.emplace_back(templateRecord->getQualifiedNameAsString(), templateSpecializationRecord);
57
return
;
58
}
59
}
60
61
// add any other records
62
m_records.emplace_back(record);
63
}
break
;
64
case
clang::Decl::Kind::Enum:
65
// TODO: add enums
66
break
;
67
default
:;
68
}
69
}
70
71
void
SerializationCodeGenerator::computeRelevantClass
(
RelevantClass
&possiblyRelevantClass)
const
72
{
73
// skip all classes which are only forward-declared
74
if
(!possiblyRelevantClass.
record
->isCompleteDefinition()) {
75
possiblyRelevantClass.
isRelevant
=
IsRelevant::No
;
76
return
;
77
}
78
79
// consider all classes for which a specialization of the "AdaptedJsonSerializable" struct is available
80
for
(
const
auto
&adaptionRecord : m_adaptionRecords) {
81
// skip all adaption records which are only included
82
if
(
isOnlyIncluded
(adaptionRecord.record)) {
83
continue
;
84
}
85
if
(adaptionRecord.qualifiedName == possiblyRelevantClass.
qualifiedName
) {
86
possiblyRelevantClass.
isRelevant
=
IsRelevant::Yes
;
87
return
;
88
}
89
}
90
91
// skip all classes which are only included
92
if
(
isOnlyIncluded
(possiblyRelevantClass.
record
)) {
93
possiblyRelevantClass.
isRelevant
=
IsRelevant::No
;
94
return
;
95
}
96
97
// consider all classes inheriting from an instantiation of "JsonSerializable" relevant
98
if
(
const
auto
*
const
relevantBase =
inheritsFromInstantiationOf
(possiblyRelevantClass.
record
,
m_qualifiedNameOfRecords
)) {
99
auto
policy = clang::PrintingPolicy(possiblyRelevantClass.
record
->getASTContext().getLangOpts());
100
policy.FullyQualifiedName =
true
;
101
policy.SuppressScope =
false
;
102
policy.SuppressUnwrittenScope =
false
;
103
policy.SplitTemplateClosers =
false
;
104
possiblyRelevantClass.
relevantBase
105
= clang::TypeName::getFullyQualifiedName(relevantBase->getType(), possiblyRelevantClass.
record
->getASTContext(), policy,
true
);
106
possiblyRelevantClass.
isRelevant
=
IsRelevant::Yes
;
107
return
;
108
}
109
}
110
111
std::vector<SerializationCodeGenerator::RelevantClass>
SerializationCodeGenerator::findRelevantClasses
()
const
112
{
113
std::vector<RelevantClass> relevantClasses;
114
for
(clang::CXXRecordDecl *
const
record : m_records) {
115
auto
&relevantClass = relevantClasses.emplace_back(record->getQualifiedNameAsString(), record);
116
computeRelevantClass
(relevantClass);
117
if
(relevantClass.isRelevant !=
IsRelevant::Yes
) {
118
relevantClasses.pop_back();
119
}
120
}
121
return
relevantClasses;
122
}
123
124
std::vector<const SerializationCodeGenerator::RelevantClass *>
SerializationCodeGenerator::findRelevantBaseClasses
(
125
const
SerializationCodeGenerator::RelevantClass
&relevantClass,
const
std::vector<SerializationCodeGenerator::RelevantClass> &relevantBases)
126
{
127
vector<const RelevantClass *> relevantBaseClasses;
128
for
(
const
RelevantClass
&otherClass : relevantBases) {
129
if
(relevantClass.
record
!= otherClass.record && relevantClass.
record
->isDerivedFrom(otherClass.record)) {
130
relevantBaseClasses.push_back(&otherClass);
131
}
132
}
133
return
relevantBaseClasses;
134
}
135
136
}
// namespace ReflectiveRapidJSON
ReflectiveRapidJSON::CodeGenerator::inheritsFromInstantiationOf
static clang::CXXBaseSpecifier * inheritsFromInstantiationOf(clang::CXXRecordDecl *record, const char *templateClass)
Returns whether the specified record inherits from an instantiation of the specified templateClass.
Definition
codegenerator.cpp:50
ReflectiveRapidJSON::CodeGenerator::isOnlyIncluded
bool isOnlyIncluded(const clang::Decl *declaration) const
Returns whether the specified declaration is only included and not part of the actual file.
Definition
codegenerator.cpp:39
ReflectiveRapidJSON::SerializationCodeGenerator::addDeclaration
void addDeclaration(clang::Decl *decl) override
Adds all class declarations (to the internal member variable m_records).
Definition
serializationcodegenerator.cpp:29
ReflectiveRapidJSON::SerializationCodeGenerator::findRelevantBaseClasses
static std::vector< const RelevantClass * > findRelevantBaseClasses(const RelevantClass &relevantClass, const std::vector< RelevantClass > &relevantBases)
Definition
serializationcodegenerator.cpp:124
ReflectiveRapidJSON::SerializationCodeGenerator::m_qualifiedNameOfRecords
const char * m_qualifiedNameOfRecords
Definition
serializationcodegenerator.h:41
ReflectiveRapidJSON::SerializationCodeGenerator::IsRelevant::Yes
@ Yes
Definition
serializationcodegenerator.h:20
ReflectiveRapidJSON::SerializationCodeGenerator::IsRelevant::No
@ No
Definition
serializationcodegenerator.h:20
ReflectiveRapidJSON::SerializationCodeGenerator::computeRelevantClass
virtual void computeRelevantClass(RelevantClass &possiblyRelevantClass) const
Definition
serializationcodegenerator.cpp:71
ReflectiveRapidJSON::SerializationCodeGenerator::m_qualifiedNameOfAdaptionRecords
const char * m_qualifiedNameOfAdaptionRecords
Definition
serializationcodegenerator.h:42
ReflectiveRapidJSON::SerializationCodeGenerator::findRelevantClasses
std::vector< RelevantClass > findRelevantClasses() const
Definition
serializationcodegenerator.cpp:111
ReflectiveRapidJSON
Definition
codegenerator.h:15
ReflectiveRapidJSON::operator<<
std::ostream & operator<<(std::ostream &os, llvm::StringRef str)
Prints an LLVM string reference without instantiating a std::string first.
Definition
serializationcodegenerator.cpp:20
serializationcodegenerator.h
ReflectiveRapidJSON::SerializationCodeGenerator::RelevantClass
Definition
serializationcodegenerator.h:21
ReflectiveRapidJSON::SerializationCodeGenerator::RelevantClass::qualifiedName
std::string qualifiedName
Definition
serializationcodegenerator.h:24
ReflectiveRapidJSON::SerializationCodeGenerator::RelevantClass::relevantBase
std::string relevantBase
Definition
serializationcodegenerator.h:25
ReflectiveRapidJSON::SerializationCodeGenerator::RelevantClass::record
clang::CXXRecordDecl * record
Definition
serializationcodegenerator.h:26
ReflectiveRapidJSON::SerializationCodeGenerator::RelevantClass::isRelevant
IsRelevant isRelevant
Definition
serializationcodegenerator.h:27
Generated on
for Reflection for RapidJSON by
1.18.0