1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <cpp2cm/cpp2cm/Map.hpp>
  7 #include <sngcpp/symbols/ClassTemplateSpecializationSymbol.hpp>
  8 #include <sngcpp/symbols/DerivedTypeSymbol.hpp>
  9 #include <sngcpp/symbols/TypedefSymbol.hpp>
 10 #include <sngcpp/symbols/ExternalTypeSymbol.hpp>
 11 #include <sngcm/ast/Identifier.hpp>
 12 #include <sngcm/ast/TypeExpr.hpp>
 13 #include <sngcm/ast/Template.hpp>
 14 #include <sngcm/ast/Expression.hpp>
 15 #include <sngcm/ast/Class.hpp>
 16 #include <soulng/util/Util.hpp>
 17 
 18 namespace cpp2cm {
 19 
 20 using namespace soulng::util;
 21 
 22 std::u32string GetFullName(sngcm::ast::Node* node)
 23 {
 24     if (!node) return std::u32string();
 25     std::u32string fullName = GetFullName(node->Parent());
 26     if (!fullName.empty())
 27     {
 28         fullName.append(1'.');
 29     }
 30     if (node->GetNodeType() == sngcm::ast::NodeType::namespaceNode)
 31     {
 32         fullName.append(static_cast<sngcm::ast::NamespaceNode*>(node)->Id()->Str());
 33     }
 34     else if (node->GetNodeType() == sngcm::ast::NodeType::classNode)
 35     {
 36         fullName.append(static_cast<sngcm::ast::ClassNode*>(node)->Id()->Str());
 37     }
 38     else
 39     {
 40         int x = 0;
 41     }
 42     return fullName;
 43 }
 44 
 45 sngcm::ast::Node* MakeQualifiedIdNode(const std::u32string& fullName)
 46 {
 47     sngcm::ast::Node* result = nullptr;
 48     if (!fullName.empty())
 49     {
 50         std::vector<std::u32string> components = Split(fullName'.');
 51         while (!components.empty())
 52         {
 53             if (result)
 54             {
 55                 result = new sngcm::ast::DotNode(soulng::lexer::Span()resultnew sngcm::ast::IdentifierNode(soulng::lexer::Span()components.back()));
 56             }
 57             else
 58             {
 59                 result = new sngcm::ast::IdentifierNode(soulng::lexer::Span()components.back());
 60             }
 61             components.pop_back();
 62         }
 63     }
 64     if (!result)
 65     {
 66         result = new sngcm::ast::IdentifierNode(soulng::lexer::Span()U"NOT_CONVERTED");
 67     }
 68     return result;
 69 }
 70 
 71 Map::Map() : symbolTable(nullptr)currentContext(nullptr)
 72 {
 73     InitNameNodeTypeMap();
 74     InitSimpleTypeMap();
 75     ClearNamespaceImports();
 76 }
 77 
 78 void Map::InitNameNodeTypeMap()
 79 {
 80     nameNodeTypeMap[U"bool"] = sngcm::ast::NodeType::boolNode;
 81     nameNodeTypeMap[U"sbyte"] = sngcm::ast::NodeType::sbyteNode;
 82     nameNodeTypeMap[U"byte"] = sngcm::ast::NodeType::byteNode;
 83     nameNodeTypeMap[U"short"] = sngcm::ast::NodeType::shortNode;
 84     nameNodeTypeMap[U"ushort"] = sngcm::ast::NodeType::ushortNode;
 85     nameNodeTypeMap[U"int"] = sngcm::ast::NodeType::intNode;
 86     nameNodeTypeMap[U"uint"] = sngcm::ast::NodeType::uintNode;
 87     nameNodeTypeMap[U"long"] = sngcm::ast::NodeType::longNode;
 88     nameNodeTypeMap[U"ulong"] = sngcm::ast::NodeType::ulongNode;
 89     nameNodeTypeMap[U"float"] = sngcm::ast::NodeType::floatNode;
 90     nameNodeTypeMap[U"double"] = sngcm::ast::NodeType::doubleNode;
 91     nameNodeTypeMap[U"char"] = sngcm::ast::NodeType::charNode;
 92     nameNodeTypeMap[U"wchar"] = sngcm::ast::NodeType::wcharNode;
 93     nameNodeTypeMap[U"uchar"] = sngcm::ast::NodeType::ucharNode;
 94     nameNodeTypeMap[U"void"] = sngcm::ast::NodeType::voidNode;
 95 }
 96 
 97 void Map::InitSimpleTypeMap()
 98 {
 99     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char_] = sngcm::ast::NodeType::charNode;
100     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char_ | sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::charNode;
101     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char_ | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::charNode;
102     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char16] = sngcm::ast::NodeType::wcharNode;
103     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char16 | sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::wcharNode;
104     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char16 | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::wcharNode;
105     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char32] = sngcm::ast::NodeType::ucharNode;
106     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char32 | sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::ucharNode;
107     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::char32 | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::ucharNode;
108     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::wchar] = sngcm::ast::NodeType::ucharNode;
109     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::wchar | sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::ucharNode;
110     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::wchar | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::ucharNode;
111     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::bool_] = sngcm::ast::NodeType::boolNode;
112     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::short_] = sngcm::ast::NodeType::shortNode;
113     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::short_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::shortNode;
114     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::short_ | sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::shortNode;
115     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::short_ | sngcpp::ast::SimpleTypeSpecifierFlags::signed_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::shortNode;
116     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::short_ | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::ushortNode;
117     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::short_ | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::ushortNode;
118     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::intNode;
119     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::intNode;
120     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::int_ | sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::intNode;
121     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::uintNode;
122     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::int_ | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::uintNode;
123     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::long_] = sngcm::ast::NodeType::longNode;
124     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::long_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::longNode;
125     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::long_ | sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::longNode;
126     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::long_ | sngcpp::ast::SimpleTypeSpecifierFlags::signed_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::longNode;
127     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::longLong_] = sngcm::ast::NodeType::longNode;
128     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::longLong_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::longNode;
129     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::longLong_ | sngcpp::ast::SimpleTypeSpecifierFlags::signed_] = sngcm::ast::NodeType::longNode;
130     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::longLong_ | sngcpp::ast::SimpleTypeSpecifierFlags::signed_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::longNode;
131     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::long_ | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::ulongNode;
132     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::long_ | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::ulongNode;
133     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::longLong_ | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_] = sngcm::ast::NodeType::ulongNode;
134     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::longLong_ | sngcpp::ast::SimpleTypeSpecifierFlags::unsigned_ | sngcpp::ast::SimpleTypeSpecifierFlags::int_] = sngcm::ast::NodeType::ulongNode;
135     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::float_] = sngcm::ast::NodeType::floatNode;
136     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::double_] = sngcm::ast::NodeType::doubleNode;
137     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::double_ | sngcpp::ast::SimpleTypeSpecifierFlags::long_] = sngcm::ast::NodeType::doubleNode;
138     simpleTypeMap[sngcpp::ast::SimpleTypeSpecifierFlags::void_] = sngcm::ast::NodeType::voidNode;
139 }
140 
141 sngcm::ast::Node* Map::CreateNode(sngcm::ast::NodeType nodeType)
142 {
143     if (nodeType != sngcm::ast::NodeType::maxNode)
144     {
145         return sngcm::ast::NodeFactory::Instance().CreateNode(nodeTypesoulng::lexer::Span());
146     }
147     return nullptr;
148 }
149 
150 sngcm::ast::Node* Map::CreateNode(const std::u32string& name)
151 {
152     auto it = nameNodeTypeMap.find(name);
153     if (it != nameNodeTypeMap.cend())
154     {
155         sngcm::ast::NodeType nodeType = it->second;
156         return CreateNode(nodeType);
157     }
158     return new sngcm::ast::IdentifierNode(soulng::lexer::Span()name);
159 }
160 
161 void Map::MapNs(const std::u32string& sourceconst std::u32string& target)
162 {
163     nsMap[source] = target;
164 }
165 
166 std::u32string Map::GetNs(const std::u32string& source) const
167 {
168     auto it = nsMap.find(source);
169     if (it != nsMap.cend())
170     {
171         return it->second;
172     }
173     return source;
174 }
175 
176 void Map::AddSourceXmlDoc(sngxml::dom::Document* sourceXmlDocconst std::u32string& projectName)
177 {
178     sourceXmlDocs.push_back(sourceXmlDoc);
179     projectSourceXmlDocMap[projectName] = sourceXmlDoc;
180 }
181 
182 void Map::SetSymbolTable(sngcpp::symbols::SymbolTable* symbolTable_)
183 {
184     symbolTable = symbolTable_;
185 }
186 
187 sngcm::ast::NodeType Map::MapSimpleType(sngcpp::ast::SimpleTypeSpecifierFlags flags)
188 {
189     sngcm::ast::NodeType nodeType = sngcm::ast::NodeType::maxNode;
190     auto it = simpleTypeMap.find(flags);
191     if (it != simpleTypeMap.cend())
192     {
193         nodeType = it->second;
194     }
195     return nodeType;
196 }
197 
198 sngcm::ast::NodeType Map::MapSimpleType(sngcpp::symbols::SimpleTypeSymbol* simpleTypeSymbol)
199 {
200     return MapSimpleType(simpleTypeSymbol->Flags());
201 }
202 
203 sngcm::ast::Node* Map::MakeDerivedType(sngcm::ast::Node* nodeconst std::std::vector<sngcpp::symbols::Derivation>&derivations)
204 {
205     bool hasConst = false;
206     bool lvalueRef = false;
207     bool rvalueRef = false;
208     for (auto derivation : derivations)
209     {
210         switch (derivation)
211         {
212             case sngcpp::symbols::Derivation::const_: hasConst = true; break;
213             case sngcpp::symbols::Derivation::lvalueRef: lvalueRef = true;  break;
214             case sngcpp::symbols::Derivation::rvalueRef: rvalueRef = true; break;
215             case sngcpp::symbols::Derivation::ptr: node = new sngcm::ast::PointerNode(soulng::lexer::Span()node); break;
216             case sngcpp::symbols::Derivation::base: break;
217             default:
218             {
219                 return nullptr;
220             }
221         }
222     }
223     if (lvalueRef)
224     {
225         node = new sngcm::ast::LValueRefNode(soulng::lexer::Span()node);
226     }
227     else if (rvalueRef)
228     {
229         node = new sngcm::ast::RValueRefNode(soulng::lexer::Span()node);
230     }
231     if (hasConst)
232     {
233         node = new sngcm::ast::ConstNode(soulng::lexer::Span()node);
234     }
235     return node;
236 }
237 
238 sngcm::ast::IdentifierNode* Map::MapFullTypeName(sngcpp::symbols::TypeSymbol* type)
239 {
240     std::u32string fullTypeName;
241     std::u32string fullNamespaceName;
242     std::vector<sngcpp::symbols::Symbol*> parents;
243     bool nonNamespaceParent = false;
244     sngcpp::symbols::Symbol* parent = type->Parent();
245     while (parent)
246     {
247         parents.push_back(parent);
248         parent = parent->Parent();
249     }
250     int n = parents.size();
251     for (int i = n - 1; i >= 0; --i)
252     {
253         sngcpp::symbols::Symbol* parent = parents[i];
254         if (parent->IsNamespaceSymbol())
255         {
256             if (!parent->Name().empty())
257             {
258                 std::u32string mappedNs = GetNs(parent->Name());
259                 if (!mappedNs.empty())
260                 {
261                     if (!fullTypeName.empty())
262                     {
263                         fullTypeName.append(1'.');
264                     }
265                     fullTypeName.append(mappedNs);
266                     if (!fullNamespaceName.empty())
267                     {
268                         fullNamespaceName.append(1'.');
269                     }
270                     fullNamespaceName.append(mappedNs);
271                 }
272             }
273         }
274         else
275         {
276             if (!fullTypeName.empty())
277             {
278                 fullTypeName.append(1'.');
279             }
280             fullTypeName.append(parent->Name());
281             nonNamespaceParent = true;
282         }
283     }
284     std::u32string currentNamespaceName = GetFullName(currentContext->currentNamespace);
285     if (!nonNamespaceParent && currentNamespaceName == fullNamespaceName)
286     {
287         return new sngcm::ast::IdentifierNode(soulng::lexer::Span()type->Name());
288     }
289     if (!fullTypeName.empty())
290     {
291         fullTypeName.append(1'.');
292     }
293     fullTypeName.append(type->Name());
294     return new sngcm::ast::IdentifierNode(soulng::lexer::Span()fullTypeName);
295 }
296 
297 sngcm::ast::Node* Map::MapType(sngcpp::symbols::TypeSymbol* typesngxml::dom::Document*& sourceXmlDoc)
298 {
299     if (!sourceXmlDoc)
300     {
301         auto it = projectSourceXmlDocMap.find(type->ProjectName());
302         if (it != projectSourceXmlDocMap.cend())
303         {
304             sourceXmlDoc = it->second;
305         }
306     }
307     if (type->IsClassTemplateSpecializationSymbol())
308     {
309         sngcpp::symbols::ClassTemplateSpecializationSymbol* specialization = static_cast<sngcpp::symbols::ClassTemplateSpecializationSymbol*>(type);
310         sngcpp::symbols::TypeSymbol* primaryType = specialization->PrimaryClassTemplateSymbol();
311         std::unique_ptr<sngcm::ast::Node> primaryNode(MapType(primaryTypesourceXmlDoc));
312         if (!primaryNode)
313         {
314             primaryNode.reset(new sngcm::ast::IdentifierNode(soulng::lexer::Span()U"NOT_CONVERTED"));
315         }
316         std::unique_ptr<sngcm::ast::TemplateIdNode> templateIdNode(new sngcm::ast::TemplateIdNode(soulng::lexer::Span()primaryNode.release()));
317         for (const auto& templateArgumentType : specialization->TemplateArgumentSymbols())
318         {
319             std::unique_ptr<sngcm::ast::Node> templateArgumentNode(MapType(templateArgumentTypesourceXmlDoc));
320             if (!templateArgumentNode)
321             {
322                 templateArgumentNode.reset(new sngcm::ast::IdentifierNode(soulng::lexer::Span()U"NOT_CONVERTED"));
323             }
324             templateIdNode->AddTemplateArgument(templateArgumentNode.release());
325         }
326         return templateIdNode.release();
327     }
328     else if (type->IsClassTypeSymbol())
329     {
330         sngcpp::symbols::ClassTypeSymbol* classTypeSymbol = static_cast<sngcpp::symbols::ClassTypeSymbol*>(type);
331         if (classTypeSymbol->ProjectName() != currentProjectName)
332         {
333             if (sourceXmlDoc)
334             {
335                 sngxml::dom::Element* element = sourceXmlDoc->GetElementById(classTypeSymbol->Id());
336                 if (element)
337                 {
338                     std::u32string target = element->GetAttribute(U"target");
339                     if (!target.empty())
340                     {
341                         target = RemoveNamespace(target);
342                         return CreateNode(target);
343                     }
344                 }
345             }
346         }
347         sngcm::ast::Node* parentNode = nullptr;
348         sngcpp::symbols::Symbol* parent = classTypeSymbol->Parent();
349         auto it = currentContext->containerMap.find(parent);
350         if (it != currentContext->containerMap.cend())
351         {
352             parentNode = it->second;
353         }
354         if (parentNode == currentContext->currentContainerNode)
355         {
356             return new sngcm::ast::IdentifierNode(soulng::lexer::Span()classTypeSymbol->Name());
357         }
358         else if (parentNode == nullptr)
359         {
360             return MapFullTypeName(classTypeSymbol);
361         }
362         else if (currentContext->currentContainerNode != nullptr)
363         {
364             std::u32string fullName = GetFullName(currentContext->currentContainerNode);
365             if (!fullName.empty())
366             {
367                 fullName.append(1'.');
368             }
369             fullName.append(classTypeSymbol->Name());
370             return MakeQualifiedIdNode(fullName);
371         }
372     }
373     else if (type->IsEnumTypeSymbol())
374     {
375         sngcpp::symbols::EnumTypeSymbol* enumTypeSymbol = static_cast<sngcpp::symbols::EnumTypeSymbol*>(type);
376         if (enumTypeSymbol->ProjectName() != currentProjectName)
377         {
378             if (sourceXmlDoc)
379             {
380                 sngxml::dom::Element* element = sourceXmlDoc->GetElementById(enumTypeSymbol->Id());
381                 if (element)
382                 {
383                     std::u32string target = element->GetAttribute(U"target");
384                     if (!target.empty())
385                     {
386                         target = RemoveNamespace(target);
387                         return CreateNode(target);
388                     }
389                 }
390             }
391         }
392         sngcm::ast::Node* parentNode = nullptr;
393         sngcpp::symbols::Symbol* parent = enumTypeSymbol->Parent();
394         auto it = currentContext->containerMap.find(parent);
395         if (it != currentContext->containerMap.cend())
396         {
397             parentNode = it->second;
398         }
399         if (parentNode == currentContext->currentContainerNode)
400         {
401             return new sngcm::ast::IdentifierNode(soulng::lexer::Span()enumTypeSymbol->Name());
402         }
403         else if (parentNode == nullptr)
404         {
405             return MapFullTypeName(enumTypeSymbol);
406         }
407         else if (currentContext->currentContainerNode != nullptr)
408         {
409             std::u32string fullName = GetFullName(currentContext->currentContainerNode);
410             if (!fullName.empty())
411             {
412                 fullName.append(1'.');
413             }
414             fullName.append(enumTypeSymbol->Name());
415             return MakeQualifiedIdNode(fullName);
416         }
417     }
418     else if (type->IsSimpleTypeSymbol())
419     {
420         sngcpp::symbols::SimpleTypeSymbol* simpleTypeSymbol = static_cast<sngcpp::symbols::SimpleTypeSymbol*>(type);
421         sngcm::ast::NodeType nodeType = MapSimpleType(simpleTypeSymbol);
422         return CreateNode(nodeType);
423     }
424     else if (type->IsDerivedTypeSymbol())
425     {
426         sngcpp::symbols::DerivedTypeSymbol* derivedTypeSymbol = static_cast<sngcpp::symbols::DerivedTypeSymbol*>(type);
427         sngcm::ast::Node* node = MapType(derivedTypeSymbol->BaseType()sourceXmlDoc);
428         if (node)
429         {
430             return MakeDerivedType(nodederivedTypeSymbol->Derivations());
431         }
432     }
433     else if (type->IsExternalTypeSymbol())
434     {
435         sngcpp::symbols::ExternalTypeSymbol* externalTypeSymbol = static_cast<sngcpp::symbols::ExternalTypeSymbol*>(type);
436         if (sourceXmlDoc)
437         {
438             sngxml::dom::Element* element = sourceXmlDoc->GetElementById(externalTypeSymbol->Id());
439             if (element)
440             {
441                 std::u32string target = element->GetAttribute(U"target");
442                 if (!target.empty())
443                 {
444                     target = RemoveNamespace(target);
445                     return CreateNode(target);
446                 }
447             }
448         }
449     }
450     else if (type->IsTypedefSymbol())
451     {
452         sngcpp::symbols::TypedefSymbol* typedefSymbol = static_cast<sngcpp::symbols::TypedefSymbol*>(type);
453         if (sourceXmlDoc)
454         {
455             std::u32string id = typedefSymbol->Id();
456             if (!typedefSymbol->PrimaryId().empty())
457             {
458                 id = typedefSymbol->PrimaryId();
459             }
460             sngxml::dom::Element* element = sourceXmlDoc->GetElementById(id);
461             if (element)
462             {
463                 std::u32string target = element->GetAttribute(U"target");
464                 if (!target.empty())
465                 {
466                     if (typedefSymbol->Parent()->IsTypeSymbol())
467                     {
468                         sngxml::dom::Document* sxmldoc = nullptr;
469                         sngcm::ast::Node* parentNode = MapType(static_cast<sngcpp::symbols::TypeSymbol*>(typedefSymbol->Parent())sxmldoc);
470                         sngcm::ast::DotNode* dotNode = new sngcm::ast::DotNode(soulng::lexer::Span()parentNodestatic_cast<sngcm::ast::IdentifierNode*>(CreateNode(target)));
471                         return dotNode;
472                     }
473                     target = RemoveNamespace(target);
474                     return CreateNode(target);
475                 }
476             }
477         }
478     }
479     else if (type->IsTemplateParameterSymbol())
480     {
481         return CreateNode(type->Name());
482     }
483     return nullptr;
484 }
485 
486 sngcm::ast::IdentifierNode* Map::MapMemberSymbol(sngcpp::symbols::Symbol* memberSymbolstd::u32string& args)
487 {
488     sngcpp::symbols::Symbol* parent = memberSymbol->Parent();
489     if (!parent) return nullptr;
490     if (parent->ProjectName() == currentProjectName)
491     {
492         return new sngcm::ast::IdentifierNode(soulng::lexer::Span()memberSymbol->Name());
493     }
494     std::u32string memberId = memberSymbol->Id();
495     if (memberSymbol->IsCallableSymbol())
496     {
497         sngcpp::symbols::CallableSymbol* callableSymbol = static_cast<sngcpp::symbols::CallableSymbol*>(memberSymbol);
498         memberId = callableSymbol->FunctionId();
499     }
500     auto it = projectSourceXmlDocMap.find(parent->ProjectName());
501     if (it != projectSourceXmlDocMap.cend())
502     {
503         sngxml::dom::Document* sourceXmlDoc = it->second;
504         sngxml::dom::Element* element = sourceXmlDoc->GetElementById(memberId);
505         if (element)
506         {
507             std::u32string target = element->GetAttribute(U"target");
508             if (!target.empty())
509             {
510                 args = element->GetAttribute(U"args");
511                 target = RemoveNamespace(target);
512                 return new sngcm::ast::IdentifierNode(soulng::lexer::Span()target);
513             }
514         }
515     }
516     for (sngxml::dom::Document* sourceXmlDoc : sourceXmlDocs)
517     {
518         sngxml::dom::Element* element = sourceXmlDoc->GetElementById(memberId);
519         if (element)
520         {
521             std::u32string target = element->GetAttribute(U"target");
522             if (!target.empty())
523             {
524                 args = element->GetAttribute(U"args");
525                 target = RemoveNamespace(target);
526                 return new sngcm::ast::IdentifierNode(soulng::lexer::Span()target);
527             }
528         }
529     }
530     return nullptr;
531 }
532 
533 sngcm::ast::IdentifierNode* Map::MapFunctionSymbol(sngcpp::symbols::CallableSymbol* callableSymbolstd::u32string& args)
534 {
535     std::u32string functionId = callableSymbol->FunctionId();
536     auto it = projectSourceXmlDocMap.find(callableSymbol->ProjectName());
537     if (it != projectSourceXmlDocMap.cend())
538     {
539         sngxml::dom::Document* sourceXmlDoc = it->second;
540         sngxml::dom::Element* element = sourceXmlDoc->GetElementById(functionId);
541         if (element)
542         {
543             std::u32string target = element->GetAttribute(U"target");
544             if (!target.empty())
545             {
546                 args = element->GetAttribute(U"args");
547                 target = RemoveNamespace(target);
548                 return new sngcm::ast::IdentifierNode(soulng::lexer::Span()target);
549             }
550         }
551     }
552     for (sngxml::dom::Document* sourceXmlDoc : sourceXmlDocs)
553     {
554         sngxml::dom::Element* element = sourceXmlDoc->GetElementById(functionId);
555         if (element)
556         {
557             std::u32string target = element->GetAttribute(U"target");
558             if (!target.empty())
559             {
560                 args = element->GetAttribute(U"args");
561                 target = RemoveNamespace(target);
562                 return new sngcm::ast::IdentifierNode(soulng::lexer::Span()target);
563             }
564         }
565     }
566     return nullptr;
567 }
568 
569 void Map::ClearNamespaceImports()
570 {
571     namespaceImports.clear();
572     namespaceImports.insert(U"System");
573     namespaceImports.insert(U"System.Collections");
574 }
575 
576 std::u32string Map::RemoveNamespace(const std::u32string& qid)
577 {
578     if (qid.find(':') != std::string::npos)
579     {
580         std::vector<std::u32string> components = Split(qid':');
581         std::u32string namespacePart = components.front();
582         namespaceImports.insert(namespacePart);
583         return components.back();
584     }
585     std::vector<std::u32string> components = Split(qid'.');
586     if (!components.empty())
587     {
588         std::u32string namespacePart;
589         for (int i = 0; i < components.size() - 1; ++i)
590         {
591             if (namespacePart.empty())
592             {
593                 namespacePart = components[i];
594             }
595             else
596             {
597                 namespacePart.append(1'.').append(components[i]);
598             }
599         }
600         if (!namespacePart.empty())
601         {
602             namespaceImports.insert(namespacePart);
603         }
604         return components.back();
605     }
606     return qid;
607 }
608 
609 sngcm::ast::Specifiers MapSpecifiers(sngcpp::ast::Specifier specifiers)
610 {
611     sngcm::ast::Specifiers mappedSpecifiers = sngcm::ast::Specifiers::none;
612     if ((specifiers & sngcpp::ast::Specifier::static_) != sngcpp::ast::Specifier::none)
613     {
614         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::static_;
615     }
616     if ((specifiers & sngcpp::ast::Specifier::constExpr) != sngcpp::ast::Specifier::none)
617     {
618         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::constexpr_;
619     }
620     if ((specifiers & sngcpp::ast::Specifier::const_) != sngcpp::ast::Specifier::none)
621     {
622         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::const_;
623     }
624     if ((specifiers & sngcpp::ast::Specifier::default_) != sngcpp::ast::Specifier::none)
625     {
626         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::default_;
627     }
628     if ((specifiers & sngcpp::ast::Specifier::delete_) != sngcpp::ast::Specifier::none)
629     {
630         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::suppress_;
631     }
632     if ((specifiers & sngcpp::ast::Specifier::explicit_) != sngcpp::ast::Specifier::none)
633     {
634         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::explicit_;
635     }
636     if ((specifiers & sngcpp::ast::Specifier::inline_) != sngcpp::ast::Specifier::none)
637     {
638         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::inline_;
639     }
640     if ((specifiers & sngcpp::ast::Specifier::override_) != sngcpp::ast::Specifier::none)
641     {
642         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::override_;
643     }
644     if ((specifiers & sngcpp::ast::Specifier::private_) != sngcpp::ast::Specifier::none)
645     {
646         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::private_;
647     }
648     if ((specifiers & sngcpp::ast::Specifier::protected_) != sngcpp::ast::Specifier::none)
649     {
650         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::protected_;
651     }
652     if ((specifiers & sngcpp::ast::Specifier::public_) != sngcpp::ast::Specifier::none)
653     {
654         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::public_;
655     }
656     if ((specifiers & sngcpp::ast::Specifier::pure_) != sngcpp::ast::Specifier::none)
657     {
658         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::abstract_;
659     }
660     if ((specifiers & sngcpp::ast::Specifier::virtual_) != sngcpp::ast::Specifier::none)
661     {
662         mappedSpecifiers = mappedSpecifiers | sngcm::ast::Specifiers::virtual_;
663     }
664     if ((mappedSpecifiers & sngcm::ast::Specifiers::abstract_) != sngcm::ast::Specifiers::none)
665     {
666         if ((mappedSpecifiers & sngcm::ast::Specifiers::virtual_) != sngcm::ast::Specifiers::none)
667         {
668             mappedSpecifiers = mappedSpecifiers & ~sngcm::ast::Specifiers::virtual_;
669         }
670     }
671     return mappedSpecifiers;
672 }
673 
674 sngcm::ast::Specifiers MapAccess(sngcpp::symbols::SymbolAccess access)
675 {
676     switch (access)
677     {
678         case sngcpp::symbols::SymbolAccess::private_: return sngcm::ast::Specifiers::private_;
679         case sngcpp::symbols::SymbolAccess::protected_: return sngcm::ast::Specifiers::protected_;
680         case sngcpp::symbols::SymbolAccess::public_: return sngcm::ast::Specifiers::public_;
681     }
682     return sngcm::ast::Specifiers::none;
683 }
684 
685 } // namespace cpp2cm