Skip to content

Commit 6fa9e8c

Browse files
committed
Be more serious on templates
1 parent e37f709 commit 6fa9e8c

15 files changed

+370
-123
lines changed

code/library/Registry.cpp

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,12 @@ namespace architect
120120
return ns;
121121
}
122122

123-
Symbol *Registry::createSymbol(SymbolType type)
123+
Symbol *Registry::createSymbol(SymbolType type, bool defined)
124124
{
125125
auto symbol = new Symbol();
126126
symbol->id = _nextSymbolId;
127127
symbol->type = type;
128+
symbol->defined = defined;
128129
_symbols.insert(std::pair<SymbolId, Symbol *>(_nextSymbolId, symbol));
129130
++_nextSymbolId;
130131
return symbol;
@@ -276,10 +277,24 @@ namespace architect
276277

277278
if (symbol->type != otherSymbol->type)
278279
return false;
280+
if (symbol->defined != otherSymbol->defined)
281+
return false;
282+
279283
if (symbol->identifier.name != otherSymbol->identifier.name)
280284
return false;
281285
if (symbol->identifier.type != otherSymbol->identifier.type)
282286
return false;
287+
288+
if (symbol->templateParameters.size() != otherSymbol->templateParameters.size())
289+
return false;
290+
291+
for (auto itTemplateParameterItem = symbol->templateParameters.begin(), itOtherTemplateParameterItem = otherSymbol->templateParameters.begin();
292+
itTemplateParameterItem != symbol->templateParameters.end();
293+
++itTemplateParameterItem, ++itOtherTemplateParameterItem)
294+
{
295+
if (*itTemplateParameterItem != *itOtherTemplateParameterItem)
296+
return false;
297+
}
283298

284299
const Namespace *iterNs = symbol->ns;
285300
const Namespace *iterOtherNs = otherSymbol->ns;
@@ -331,26 +346,4 @@ namespace architect
331346

332347
return true;
333348
}
334-
335-
void Registry::dump(std::ostream &stream) const
336-
{
337-
for (auto &pair : _symbols)
338-
{
339-
const Symbol *symbol = pair.second;
340-
341-
stream << symbol->getFullName() << ":\n";
342-
343-
for (auto &refPair : symbol->references)
344-
{
345-
stream << " " << _symbols.at(refPair.first)->getFullName() << "\n";
346-
347-
for (auto &reference : refPair.second)
348-
{
349-
stream << " " << (int)reference.type << " " << reference.location.line << "\n";
350-
}
351-
}
352-
stream << "\n";
353-
}
354-
}
355-
356349
}

code/library/Symbol.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace architect
2323
switch (type)
2424
{
2525
case SymbolType::GLOBAL:
26+
case SymbolType::GLOBAL_TEMPLATE:
2627
{
2728
name = identifier.type + " " + identifier.name;
2829
break;
@@ -40,6 +41,21 @@ namespace architect
4041
iterNs = iterNs->parent;
4142
}
4243

44+
if (!templateParameters.empty())
45+
{
46+
name += "<";
47+
bool notFirst = false;
48+
for (auto &param : templateParameters)
49+
{
50+
if (notFirst)
51+
name += ", ";
52+
else
53+
notFirst = true;
54+
name += param;
55+
}
56+
name += ">";
57+
}
58+
4359
return name;
4460
}
4561
}

code/library/clang.cpp

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,22 +86,24 @@ namespace architect
8686
public:
8787
VisitorContext(Registry *registry, Namespace *nameSpace);
8888

89-
VisitorContext setReferenceType(ReferenceType referenceType);
89+
VisitorContext setReferenceType(ReferenceType referenceType) const;
9090

9191
VisitorContext declareNameSpace(const CXCursor &cursor);
9292

93-
VisitorContext declareGlobal(const CXCursor &cursor);
93+
VisitorContext declareGlobal(const CXCursor &cursor, bool isTemplate, bool &wasDefined);
9494

95-
VisitorContext declareRecord(const CXCursor &cursor);
95+
VisitorContext declareRecord(const CXCursor &cursor, bool isTemplate, bool &wasDefined);
96+
97+
VisitorContext declareTemplateParameter(const CXCursor &cursor);
9698

9799
VisitorContext declareTypedef(const CXCursor &cursor);
98100

99101
void declareReference(const CXCursor &cursor, const CXCursor &referenceCursor);
100102

101103
private:
102-
Symbol *getSymbol(const CXCursor &cursor, SymbolIdentifier &identifier);
104+
Symbol *getSymbol(const CXCursor &cursor, SymbolIdentifier &identifier) const;
103105

104-
Symbol *declareSymbol(SymbolType symbolType, const CXCursor &cursor, const CXCursor &referenceCursor);
106+
Symbol *declareSymbol(SymbolType symbolType, const CXCursor &cursor, const CXCursor &referenceCursor, bool &wasDefined);
105107

106108
static CXChildVisitResult nameSpaceVisitor(CXCursor cursor, CXCursor parent, CXClientData clientData);
107109

@@ -110,6 +112,7 @@ namespace architect
110112
Symbol *_currentSymbol;
111113
ReferenceType _referenceType;
112114
bool _inRecord;
115+
bool _inTemplateParameter;
113116
};
114117

115118
VisitorContext::VisitorContext(Registry *registry, Namespace *ns)
@@ -118,9 +121,10 @@ namespace architect
118121
, _currentSymbol(nullptr)
119122
, _referenceType(ReferenceType::ASSOCIATION)
120123
, _inRecord(false)
124+
, _inTemplateParameter(false)
121125
{}
122126

123-
VisitorContext VisitorContext::setReferenceType(ReferenceType referenceType)
127+
VisitorContext VisitorContext::setReferenceType(ReferenceType referenceType) const
124128
{
125129
VisitorContext subContext(*this);
126130
subContext._referenceType = referenceType;
@@ -140,34 +144,49 @@ namespace architect
140144
return subContext;
141145
}
142146

143-
VisitorContext VisitorContext::declareGlobal(const CXCursor &cursor)
147+
VisitorContext VisitorContext::declareGlobal(const CXCursor &cursor, bool isTemplate, bool &wasDefined)
144148
{
145149
VisitorContext subContext(*this);
146150
subContext._referenceType = ReferenceType::ASSOCIATION;
147151

148152
if (!_inRecord)
149153
{
150-
Symbol *symbol = declareSymbol(SymbolType::GLOBAL, cursor, cursor);
154+
Symbol *symbol = declareSymbol(isTemplate ? SymbolType::GLOBAL_TEMPLATE : SymbolType::GLOBAL, cursor, cursor, wasDefined);
151155
subContext._currentSymbol = symbol;
152156
}
153157

154158
return subContext;
155159
}
156160

157-
VisitorContext VisitorContext::declareRecord(const CXCursor &cursor)
161+
VisitorContext VisitorContext::declareRecord(const CXCursor &cursor, bool isTemplate, bool &wasDefined)
158162
{
159-
Symbol *symbol = declareSymbol(SymbolType::RECORD, cursor, cursor);
163+
Symbol *symbol = declareSymbol(isTemplate ? SymbolType::RECORD_TEMPLATE : SymbolType::RECORD, cursor, cursor, wasDefined);
160164

161165
VisitorContext subContext(*this);
162166
subContext._currentSymbol = symbol;
163167
subContext._referenceType = ReferenceType::COMPOSITION;
164168
subContext._inRecord = true;
165169
return subContext;
166170
}
171+
172+
VisitorContext VisitorContext::declareTemplateParameter(const CXCursor &cursor)
173+
{
174+
if (_inTemplateParameter)
175+
return *this;
176+
177+
auto name = clang_getCString(clang_getCursorSpelling(cursor));
178+
_currentSymbol->templateParameters.push_back(name);
179+
180+
VisitorContext subContext(*this);
181+
subContext._referenceType = ReferenceType::ASSOCIATION;
182+
subContext._inTemplateParameter = true;
183+
return subContext;
184+
}
167185

168186
VisitorContext VisitorContext::declareTypedef(const CXCursor &cursor)
169187
{
170-
Symbol *symbol = declareSymbol(SymbolType::TYPEDEF, cursor, cursor);
188+
bool wasDefined;
189+
Symbol *symbol = declareSymbol(SymbolType::TYPEDEF, cursor, cursor, wasDefined);
171190

172191
VisitorContext subContext(*this);
173192
subContext._currentSymbol = symbol;
@@ -190,7 +209,7 @@ namespace architect
190209
}
191210
}
192211

193-
Symbol *VisitorContext::getSymbol(const CXCursor &cursor, SymbolIdentifier &identifier)
212+
Symbol *VisitorContext::getSymbol(const CXCursor &cursor, SymbolIdentifier &identifier) const
194213
{
195214
CXType type = clang_getCursorType(cursor);
196215

@@ -241,19 +260,23 @@ namespace architect
241260
return nullptr;
242261
}
243262

244-
Symbol *VisitorContext::declareSymbol(SymbolType symbolType, const CXCursor &cursor, const CXCursor &referenceCursor)
263+
Symbol *VisitorContext::declareSymbol(SymbolType symbolType, const CXCursor &cursor, const CXCursor &referenceCursor, bool &wasDefined)
245264
{
246265
SymbolIdentifier identifier;
247266
Symbol *symbol = getSymbol(cursor, identifier);
248267
if (!symbol)
249268
{
250-
symbol = _registry->createSymbol(symbolType);
269+
symbol = _registry->createSymbol(symbolType, false);
251270
symbol->identifier = identifier;
252271
symbol->ns = _currentNameSpace;
253272

254273
_currentNameSpace->symbols.insert(std::pair<SymbolIdentifier, Symbol *>(identifier, symbol));
255274
}
256275

276+
wasDefined = symbol->defined;
277+
if (clang_isCursorDefinition(cursor))
278+
symbol->defined = true;
279+
257280
if (_currentSymbol && symbol != _currentSymbol)
258281
{
259282
Reference reference;
@@ -279,10 +302,12 @@ namespace architect
279302
return CXChildVisit_Continue;
280303
}
281304

305+
CXChildVisitResult functionVisitor(CXCursor cursor, CXCursor parent, CXClientData clientData);
282306
CXChildVisitResult globalVisitor(CXCursor cursor, CXCursor parent, CXClientData clientData);
283307

284308
bool handleReference(CXCursor &cursor, VisitorContext &context)
285309
{
310+
auto name = clang_getCString(clang_getCursorSpelling(cursor));
286311
CXCursorKind kind = clang_getCursorKind(cursor);
287312
switch (kind)
288313
{
@@ -293,9 +318,7 @@ namespace architect
293318
CXCursor referencedCursor = clang_getCursorReferenced(cursor);
294319
if (!clang_Cursor_isNull(referencedCursor))
295320
{
296-
VisitorContext subContext = context.setReferenceType(ReferenceType::TEMPLATE);
297-
//subContext.declareReference(referencedCursor, cursor);
298-
globalVisitor(referencedCursor, cursor, &subContext);
321+
globalVisitor(referencedCursor, cursor, &context);
299322
}
300323
}
301324
break;
@@ -314,6 +337,15 @@ namespace architect
314337
break;
315338
}
316339

340+
case CXCursor_TemplateTypeParameter:
341+
case CXCursor_NonTypeTemplateParameter:
342+
case CXCursor_TemplateTemplateParameter:
343+
{
344+
VisitorContext subContext = context.declareTemplateParameter(cursor);
345+
clang_visitChildren(cursor, functionVisitor, &subContext);
346+
break;
347+
}
348+
317349
default:
318350
return false;
319351
}
@@ -327,6 +359,7 @@ namespace architect
327359
if (handleReference(cursor, context))
328360
return CXChildVisit_Continue;
329361

362+
auto name = clang_getCString(clang_getCursorSpelling(cursor));
330363
CXCursorKind kind = clang_getCursorKind(cursor);
331364
switch (kind)
332365
{
@@ -347,6 +380,7 @@ namespace architect
347380
if (handleReference(cursor, context))
348381
return CXChildVisit_Continue;
349382

383+
auto name = clang_getCString(clang_getCursorSpelling(cursor));
350384
CXCursorKind kind = clang_getCursorKind(cursor);
351385
switch (kind)
352386
{
@@ -363,8 +397,10 @@ namespace architect
363397
case CXCursor_StructDecl:
364398
case CXCursor_UnionDecl:
365399
{
366-
VisitorContext subContext = context.declareRecord(cursor);
367-
clang_visitChildren(cursor, globalVisitor, &subContext);
400+
bool wasDefined;
401+
VisitorContext subContext = context.declareRecord(cursor, kind == CXCursor_ClassTemplate, wasDefined);
402+
if (!wasDefined)
403+
clang_visitChildren(cursor, globalVisitor, &subContext);
368404
break;
369405
}
370406

@@ -376,10 +412,13 @@ namespace architect
376412
}
377413

378414
case CXCursor_FunctionDecl:
415+
case CXCursor_FunctionTemplate:
379416
case CXCursor_VarDecl:
380417
{
381-
VisitorContext subContext = context.declareGlobal(cursor);
382-
clang_visitChildren(cursor, functionVisitor, &subContext);
418+
bool wasDefined;
419+
VisitorContext subContext = context.declareGlobal(cursor, kind == CXCursor_FunctionTemplate, wasDefined);
420+
if (!wasDefined)
421+
clang_visitChildren(cursor, functionVisitor, &subContext);
383422
break;
384423
}
385424

code/library/console.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace architect
1212
switch (type)
1313
{
1414
case ReferenceType::TEMPLATE:
15-
return "template";
15+
return "template specialization";
1616
case ReferenceType::INHERITANCE:
1717
return "inheritance";
1818
case ReferenceType::COMPOSITION:
@@ -30,8 +30,12 @@ namespace architect
3030
{
3131
case SymbolType::GLOBAL:
3232
return "global";
33+
case SymbolType::GLOBAL_TEMPLATE:
34+
return "global template";
3335
case SymbolType::RECORD:
3436
return "record";
37+
case SymbolType::RECORD_TEMPLATE:
38+
return "record template";
3539
case SymbolType::TYPEDEF:
3640
return "typedef";
3741
default:

code/library/dot.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ namespace architect
2828
template <>
2929
void insert(std::string key, std::string value)
3030
{
31-
_map.insert(std::pair<std::string, std::string>(key, value));
31+
auto it = _map.find(key);
32+
if (it == _map.end())
33+
_map.insert(std::pair<std::string, std::string>(key, value));
34+
else
35+
it->second += "," + value;
3236
}
3337

3438
private:
@@ -62,15 +66,28 @@ namespace architect
6266
attributes.insert("shape", "ellipse");
6367
break;
6468

69+
case SymbolType::GLOBAL_TEMPLATE:
70+
attributes.insert("shape", "ellipse");
71+
attributes.insert("style", "diagonals");
72+
break;
73+
6574
case SymbolType::RECORD:
6675
attributes.insert("shape", "box");
6776
break;
6877

78+
case SymbolType::RECORD_TEMPLATE:
79+
attributes.insert("shape", "box");
80+
attributes.insert("style", "diagonals");
81+
break;
82+
6983
case SymbolType::TYPEDEF:
7084
attributes.insert("shape", "octagon");
7185
break;
7286
}
7387

88+
if (!symbol->defined)
89+
attributes.insert("style", "dashed");
90+
7491
if (parameters.pretty)
7592
stream << " ";
7693
stream << symbol->id << attributes << ";";
@@ -126,6 +143,8 @@ namespace architect
126143
void dumpSymbols(const std::map<SymbolId, Symbol *> &symbols, std::ostream &stream, const FormattingParameters &parameters)
127144
{
128145
stream << "strict digraph{";
146+
if (parameters.pretty)
147+
stream << "\n";
129148

130149
for (auto &pair : symbols)
131150
{

0 commit comments

Comments
 (0)