XmlAnalyzer.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Utils.h"
  23. #include "XmlAnalyzer.h"
  24. #include "XmlSourceData.h"
  25. #include <cassert>
  26. #include <regex>
  27. extern string _sourceDir;
  28. string RemoveRefs(xml_node node)
  29. {
  30. assert(node.name() == string("type") || node.name() == string("defval") || node.name() == string("para"));
  31. string result;
  32. for (xml_node part : node.children())
  33. {
  34. if (part.name() == string("ref"))
  35. result += part.child_value();
  36. else
  37. result += part.value();
  38. }
  39. return result;
  40. }
  41. TypeAnalyzer::TypeAnalyzer(xml_node type, const TemplateSpecialization& specialization)
  42. {
  43. assert(type.name() == string("type"));
  44. fullType_ = RemoveRefs(type);
  45. fullType_ = RemoveFirst(fullType_, "URHO3D_API ");
  46. fullType_ = RemoveFirst(fullType_, " URHO3D_API");
  47. fullType_ = CutStart(fullType_, "constexpr ");
  48. fullType_ = ReplaceAll(fullType_, " *", "*");
  49. fullType_ = ReplaceAll(fullType_, " &", "&");
  50. fullType_ = ReplaceAll(fullType_, "< ", "<");
  51. fullType_ = ReplaceAll(fullType_, " >", ">");
  52. for (pair<const string, string> it : specialization)
  53. {
  54. regex rgx("\\b" + it.first + "\\b");
  55. fullType_ = regex_replace(fullType_, rgx, it.second);
  56. }
  57. isConst_ = StartsWith(fullType_, "const ");
  58. name_ = CutStart(fullType_, "const ");
  59. isRvalueReference_ = EndsWith(name_, "&&");
  60. name_ = CutEnd(name_, "&&");
  61. isRefToPoiner_ = EndsWith(name_, "*&");
  62. name_ = CutEnd(name_, "*&");
  63. isDoublePointer_ = EndsWith(name_, "**");
  64. name_ = CutEnd(name_, "**");
  65. isPointer_ = EndsWith(name_, "*");
  66. name_ = CutEnd(name_, "*");
  67. isReference_ = EndsWith(name_, "&");
  68. name_ = CutEnd(name_, "&");
  69. smatch match;
  70. if (regex_match(name_, match, regex("(.+?)<(.+)>")))
  71. {
  72. templateParams_ = match[2].str();
  73. name_ = match[1].str();
  74. }
  75. }
  76. TypeAnalyzer::TypeAnalyzer(const string& typeName)
  77. {
  78. fullType_ = typeName;
  79. name_ = typeName;
  80. isConst_ = false;
  81. isPointer_ = false;
  82. isReference_ = false;
  83. isRvalueReference_ = false;
  84. isDoublePointer_ = false;
  85. isRefToPoiner_ = false;
  86. }
  87. // ============================================================================
  88. ParamAnalyzer::ParamAnalyzer(xml_node param, const TemplateSpecialization& specialization)
  89. : node_(param)
  90. , specialization_(specialization)
  91. {
  92. assert(node_.name() == string("param"));
  93. }
  94. string ParamAnalyzer::ToString() const
  95. {
  96. string type = GetType().ToString();
  97. assert(!type.empty());
  98. string name = GetDeclname();
  99. assert(!name.empty());
  100. return type + " " + name;
  101. }
  102. TypeAnalyzer ParamAnalyzer::GetType() const
  103. {
  104. xml_node type = node_.child("type");
  105. assert(type);
  106. return TypeAnalyzer(type, specialization_);
  107. }
  108. string ParamAnalyzer::GetDeclname() const
  109. {
  110. string result = node_.child("declname").child_value();
  111. //assert(!result.empty()); TODO
  112. return result;
  113. }
  114. string ParamAnalyzer::GetDefval() const
  115. {
  116. xml_node defval = node_.child("defval");
  117. if (defval)
  118. return RemoveRefs(defval);
  119. return "";
  120. }
  121. // ============================================================================
  122. string ExtractCompoundname(xml_node compounddef)
  123. {
  124. assert(IsCompounddef(compounddef));
  125. string result = compounddef.child("compoundname").child_value();
  126. assert(!result.empty());
  127. return result;
  128. }
  129. xml_node FindSectiondef(xml_node compounddef, const string& kind)
  130. {
  131. assert(IsCompounddef(compounddef));
  132. assert(!kind.empty());
  133. for (xml_node sectiondef : compounddef.children("sectiondef"))
  134. {
  135. if (ExtractKind(sectiondef) == kind)
  136. return sectiondef;
  137. }
  138. return xml_node();
  139. }
  140. bool IsStatic(xml_node memberdef)
  141. {
  142. assert(IsMemberdef(memberdef));
  143. string staticAttr = memberdef.attribute("static").value();
  144. assert(!staticAttr.empty());
  145. return staticAttr == "yes";
  146. }
  147. bool IsExplicit(xml_node memberdef)
  148. {
  149. assert(IsMemberdef(memberdef));
  150. assert(ExtractKind(memberdef) == "function");
  151. string explicitAttr = memberdef.attribute("explicit").value();
  152. assert(!explicitAttr.empty());
  153. return explicitAttr == "yes";
  154. }
  155. string ExtractDefinition(xml_node memberdef)
  156. {
  157. assert(IsMemberdef(memberdef));
  158. string result = memberdef.child("definition").child_value();
  159. assert(!result.empty());
  160. return result;
  161. }
  162. static string BeautifyDefinition(const string& definition)
  163. {
  164. string result = definition;
  165. result = ReplaceAll(result, " **", "** ");
  166. result = ReplaceAll(result, " &&", "&& ");
  167. result = ReplaceAll(result, " *&", "*& ");
  168. result = ReplaceAll(result, " *", "* ");
  169. result = ReplaceAll(result, " &", "& ");
  170. result = ReplaceAll(result, "=", " = ");
  171. result = ReplaceAll(result, " = = ", "==");
  172. result = ReplaceAll(result, "! = ", "!=");
  173. result = ReplaceAll(result, "+ = ", "+=");
  174. result = ReplaceAll(result, "- = ", "-=");
  175. result = ReplaceAll(result, "* = ", "*=");
  176. result = ReplaceAll(result, "/ = ", "/=");
  177. result = ReplaceAll(result, "operator = ", "operator=");
  178. result = ReplaceAll(result, "operator", "operator ");
  179. while (Contains(result, " "))
  180. result = ReplaceAll(result, " ", " ");
  181. result = ReplaceAll(result, " )", ")");
  182. result = ReplaceAll(result, "< ", "<");
  183. result = ReplaceAll(result, " >", ">");
  184. result = ReplaceAll(result, "template<", "template <");
  185. return result;
  186. }
  187. string ExtractArgsstring(xml_node memberdef)
  188. {
  189. assert(IsMemberdef(memberdef));
  190. xml_node argsstring = memberdef.child("argsstring");
  191. assert(argsstring);
  192. return argsstring.child_value();
  193. }
  194. string ExtractCleanedFunctionArgsstring(xml_node memberdef)
  195. {
  196. assert(ExtractKind(memberdef) == "function");
  197. string argsstring = ExtractArgsstring(memberdef);
  198. assert(StartsWith(argsstring, "("));
  199. size_t endPos = argsstring.find_last_of(')');
  200. assert(endPos != string::npos);
  201. return argsstring.substr(1, endPos - 1);
  202. }
  203. string ExtractProt(xml_node memberdef)
  204. {
  205. assert(IsMemberdef(memberdef));
  206. string result = memberdef.attribute("prot").value();
  207. assert(!result.empty());
  208. return result;
  209. }
  210. TypeAnalyzer ExtractType(xml_node memberdef, const TemplateSpecialization& specialization)
  211. {
  212. assert(IsMemberdef(memberdef));
  213. xml_node type = memberdef.child("type");
  214. assert(type);
  215. // Doxygen bug workaround https://github.com/doxygen/doxygen/issues/7732
  216. // For user-defined conversion operator exract return type from function name
  217. if (RemoveRefs(type).empty() && ExtractKind(memberdef) == "function")
  218. {
  219. string functionName = ExtractName(memberdef);
  220. if (StartsWith(functionName, "operator "))
  221. return TypeAnalyzer(CutStart(functionName, "operator "));
  222. }
  223. return TypeAnalyzer(type, specialization);
  224. }
  225. vector<ParamAnalyzer> ExtractParams(xml_node memberdef, const TemplateSpecialization& specialization)
  226. {
  227. assert(IsMemberdef(memberdef));
  228. assert(ExtractKind(memberdef) == "function");
  229. vector<ParamAnalyzer> result;
  230. for (xml_node param : memberdef.children("param"))
  231. result.push_back(ParamAnalyzer(param, specialization));
  232. return result;
  233. }
  234. string JoinParamsTypes(xml_node memberdef, const TemplateSpecialization& specialization)
  235. {
  236. assert(IsMemberdef(memberdef));
  237. assert(ExtractKind(memberdef) == "function");
  238. string result;
  239. vector<ParamAnalyzer> params = ExtractParams(memberdef, specialization);
  240. for (const ParamAnalyzer& param : params)
  241. {
  242. if (!result.empty())
  243. result += ", ";
  244. result += param.GetType().ToString();
  245. }
  246. return result;
  247. }
  248. string JoinParamsNames(xml_node memberdef, bool skipContext)
  249. {
  250. assert(IsMemberdef(memberdef));
  251. assert(ExtractKind(memberdef) == "function");
  252. string result;
  253. vector<ParamAnalyzer> params = ExtractParams(memberdef);
  254. for (size_t i = 0; i < params.size(); i++)
  255. {
  256. ParamAnalyzer param = params[i];
  257. if (skipContext && i == 0)
  258. {
  259. assert(param.GetType().ToString() == "Context*");
  260. continue;
  261. }
  262. if (!result.empty())
  263. result += ", ";
  264. result += param.GetDeclname();
  265. }
  266. return result;
  267. }
  268. string ExtractID(xml_node node)
  269. {
  270. assert(IsMemberdef(node) || IsCompounddef(node));
  271. string result = node.attribute("id").value();
  272. assert(!result.empty());
  273. return result;
  274. }
  275. string ExtractKind(xml_node node)
  276. {
  277. assert(IsMemberdef(node) || IsCompounddef(node) || IsMember(node) || IsSectiondef(node));
  278. string result = node.attribute("kind").value();
  279. assert(!result.empty());
  280. return result;
  281. }
  282. string ExtractName(xml_node node)
  283. {
  284. assert(IsMemberdef(node) || IsEnumvalue(node));
  285. string result = node.child("name").child_value();
  286. assert(!result.empty());
  287. return result;
  288. }
  289. string ExtractLine(xml_node node)
  290. {
  291. assert(IsMemberdef(node) || IsCompounddef(node));
  292. string result = node.child("location").attribute("line").value();
  293. assert(!result.empty());
  294. return result;
  295. }
  296. string ExtractColumn(xml_node node)
  297. {
  298. assert(IsMemberdef(node) || IsCompounddef(node));
  299. string result = node.child("location").attribute("column").value();
  300. assert(!result.empty());
  301. return result;
  302. }
  303. static string DescriptionToString(xml_node description)
  304. {
  305. string result;
  306. for (xml_node para : description.children("para"))
  307. {
  308. result += RemoveRefs(para);
  309. result += " "; // To avoid gluing words from different paragraphs
  310. }
  311. return result;
  312. }
  313. string ExtractComment(xml_node node)
  314. {
  315. assert(IsMemberdef(node) || IsCompounddef(node));
  316. xml_node brief = node.child("briefdescription");
  317. assert(brief);
  318. xml_node detailed = node.child("detaileddescription");
  319. assert(detailed);
  320. return DescriptionToString(brief) + DescriptionToString(detailed);
  321. }
  322. static string HeaderFullPathToRelative(const string& fullPath)
  323. {
  324. assert(StartsWith(fullPath, _sourceDir + "/Source/Urho3D"));
  325. return ".." + CutStart(fullPath, _sourceDir + "/Source/Urho3D");
  326. }
  327. string ExtractHeaderFile(xml_node node)
  328. {
  329. assert(IsMemberdef(node) || IsCompounddef(node));
  330. xml_node location = node.child("location");
  331. assert(!location.empty());
  332. string declfile = location.attribute("declfile").value();
  333. if (EndsWith(declfile, ".h"))
  334. return HeaderFullPathToRelative(declfile);
  335. string file = location.attribute("file").value();
  336. if (EndsWith(file, ".h"))
  337. return HeaderFullPathToRelative(file);
  338. return string();
  339. }
  340. bool IsTemplate(xml_node node)
  341. {
  342. assert(IsMemberdef(node) || IsCompounddef(node));
  343. return node.child("templateparamlist");
  344. }
  345. vector<string> ExtractTemplateParams(xml_node node)
  346. {
  347. assert(IsMemberdef(node) || IsCompounddef(node));
  348. vector<string> result;
  349. xml_node templateparamlist = node.child("templateparamlist");
  350. for (xml_node param : templateparamlist.children("param"))
  351. {
  352. string type = param.child_value("type");
  353. type = CutStart(type, "class ");
  354. type = CutStart(type, "typename ");
  355. result.push_back(type);
  356. }
  357. return result;
  358. }
  359. // ============================================================================
  360. EnumAnalyzer::EnumAnalyzer(xml_node memberdef)
  361. : memberdef_(memberdef)
  362. {
  363. assert(IsMemberdef(memberdef));
  364. assert(ExtractKind(memberdef) == "enum");
  365. }
  366. string EnumAnalyzer::GetBaseType() const
  367. {
  368. string result = memberdef_.child("type").child_value();
  369. if (result.empty())
  370. return "int";
  371. return result;
  372. }
  373. string EnumAnalyzer::GetLocation() const
  374. {
  375. string baseType = GetBaseType();
  376. if (baseType == "int")
  377. return "enum " + GetTypeName() + " | File: " + GetHeaderFile();
  378. return "enum " + GetTypeName() + " : " + baseType + " | File: " + GetHeaderFile();
  379. }
  380. vector<string> EnumAnalyzer::GetEnumerators() const
  381. {
  382. vector<string> result;
  383. for (xml_node enumvalue : memberdef_.children("enumvalue"))
  384. result.push_back(ExtractName(enumvalue));
  385. return result;
  386. }
  387. // ============================================================================
  388. GlobalVariableAnalyzer::GlobalVariableAnalyzer(xml_node memberdef)
  389. : memberdef_(memberdef)
  390. {
  391. assert(IsMemberdef(memberdef));
  392. assert(ExtractKind(memberdef) == "variable");
  393. }
  394. // ============================================================================
  395. ClassAnalyzer::ClassAnalyzer(xml_node compounddef, const TemplateSpecialization& specialization)
  396. : compounddef_(compounddef)
  397. , specialization_(specialization)
  398. {
  399. assert(IsCompounddef(compounddef));
  400. }
  401. string ClassAnalyzer::GetClassName() const
  402. {
  403. string compoundname = ExtractCompoundname(compounddef_);
  404. assert(StartsWith(compoundname, "Urho3D::"));
  405. return CutStart(compoundname, "Urho3D::");
  406. }
  407. string ClassAnalyzer::GetDirName() const
  408. {
  409. string str = CutStart(GetHeaderFile(), "../");
  410. size_t pos = str.find('/');
  411. assert(pos != string::npos);
  412. return str.substr(0, pos);
  413. }
  414. bool ClassAnalyzer::IsInternal() const
  415. {
  416. if (GetHeaderFile().empty()) // Defined in *.cpp
  417. return true;
  418. if (Contains(GetClassName(), "::")) // Defined inside another class
  419. return true;
  420. return false;
  421. }
  422. vector<xml_node> ClassAnalyzer::GetMemberdefs() const
  423. {
  424. vector<xml_node> result;
  425. xml_node listofallmembers = compounddef_.child("listofallmembers");
  426. assert(listofallmembers);
  427. for (xml_node member : listofallmembers.children("member"))
  428. {
  429. xml_attribute ambiguityscope = member.attribute("ambiguityscope");
  430. if (!ambiguityscope.empty())
  431. continue;
  432. string refid = member.attribute("refid").value();
  433. assert(!refid.empty());
  434. auto it = SourceData::members_.find(refid);
  435. if (it == SourceData::members_.end())
  436. continue;
  437. xml_node memberdef = it->second;
  438. result.push_back(memberdef);
  439. }
  440. return result;
  441. }
  442. vector<string> ClassAnalyzer::GetAllPublicMembersRefids() const
  443. {
  444. vector<string> result;
  445. xml_node listofallmembers = compounddef_.child("listofallmembers");
  446. assert(listofallmembers);
  447. for (xml_node member : listofallmembers.children("member"))
  448. {
  449. string prot = member.attribute("prot").value();
  450. assert(!prot.empty());
  451. if (prot != "public")
  452. continue;
  453. xml_attribute ambiguityscope = member.attribute("ambiguityscope");
  454. if (!ambiguityscope.empty())
  455. continue;
  456. string refid = member.attribute("refid").value();
  457. assert(!refid.empty());
  458. result.push_back(refid);
  459. }
  460. return result;
  461. }
  462. static vector<xml_node> GetHiddenMemberdefs(const ClassAnalyzer& classAnalyzer)
  463. {
  464. vector<string> thisRefids = classAnalyzer.GetAllPublicMembersRefids();
  465. vector<ClassAnalyzer> baseClasses = classAnalyzer.GetBaseClasses();
  466. vector<xml_node> result;
  467. for (const ClassAnalyzer& baseClass : baseClasses)
  468. {
  469. vector<string> baseRefids = baseClass.GetAllPublicMembersRefids();
  470. for (const string& baseRefid : baseRefids)
  471. {
  472. if (CONTAINS(thisRefids, baseRefid))
  473. continue;
  474. auto it = SourceData::members_.find(baseRefid);
  475. if (it == SourceData::members_.end())
  476. continue;
  477. xml_node memberdef = it->second;
  478. result.push_back(memberdef);
  479. }
  480. }
  481. return result;
  482. }
  483. vector<string> ClassAnalyzer::GetHiddenMethods() const
  484. {
  485. vector<xml_node> hiddenMemberdefs = GetHiddenMemberdefs(*this);
  486. vector<string> result;
  487. for (xml_node memberdef : hiddenMemberdefs)
  488. {
  489. if (ExtractKind(memberdef) == "function" && !IsStatic(memberdef))
  490. result.push_back(GetFunctionDeclaration(memberdef));
  491. }
  492. sort(result.begin(), result.end());
  493. return result;
  494. }
  495. vector<string> ClassAnalyzer::GetHiddenStaticMethods() const
  496. {
  497. vector<xml_node> hiddenMemberdefs = GetHiddenMemberdefs(*this);
  498. vector<string> result;
  499. for (xml_node memberdef : hiddenMemberdefs)
  500. {
  501. if (ExtractKind(memberdef) == "function" && IsStatic(memberdef))
  502. result.push_back(GetFunctionDeclaration(memberdef));
  503. }
  504. sort(result.begin(), result.end());
  505. return result;
  506. }
  507. vector<string> ClassAnalyzer::GetHiddenFields() const
  508. {
  509. vector<xml_node> hiddenMemberdefs = GetHiddenMemberdefs(*this);
  510. vector<string> result;
  511. for (xml_node memberdef : hiddenMemberdefs)
  512. {
  513. if (ExtractKind(memberdef) == "variable" && !IsStatic(memberdef))
  514. result.push_back(GetVariableDeclaration(memberdef));
  515. }
  516. sort(result.begin(), result.end());
  517. return result;
  518. }
  519. vector<string> ClassAnalyzer::GetHiddenStaticFields() const
  520. {
  521. vector<xml_node> hiddenMemberdefs = GetHiddenMemberdefs(*this);
  522. vector<string> result;
  523. for (xml_node memberdef : hiddenMemberdefs)
  524. {
  525. if (ExtractKind(memberdef) == "variable" && IsStatic(memberdef))
  526. result.push_back(GetVariableDeclaration(memberdef));
  527. }
  528. sort(result.begin(), result.end());
  529. return result;
  530. }
  531. int ClassAnalyzer::GetInherianceDeep(int counter) const
  532. {
  533. vector<ClassAnalyzer> baseClasses = GetBaseClasses();
  534. int result = counter;
  535. for (const ClassAnalyzer& baseClass : baseClasses)
  536. {
  537. int ret = baseClass.GetInherianceDeep(counter + 1);
  538. if (ret > result)
  539. result = ret;
  540. }
  541. return result;
  542. }
  543. vector<MethodAnalyzer> ClassAnalyzer::GetAllMethods() const
  544. {
  545. vector<MethodAnalyzer> result;
  546. vector<xml_node> memberdefs = GetMemberdefs();
  547. for (xml_node memberdef : memberdefs)
  548. {
  549. if (ExtractKind(memberdef) == "function")
  550. result.push_back(MethodAnalyzer(*this, memberdef));
  551. }
  552. return result;
  553. }
  554. vector<MethodAnalyzer> ClassAnalyzer::GetAllPublicMethods() const
  555. {
  556. vector<MethodAnalyzer> result;
  557. vector<xml_node> memberdefs = GetMemberdefs();
  558. for (xml_node memberdef : memberdefs)
  559. {
  560. if (ExtractKind(memberdef) == "function" && ExtractProt(memberdef) == "public")
  561. result.push_back(MethodAnalyzer(*this, memberdef));
  562. }
  563. return result;
  564. }
  565. vector<MethodAnalyzer> ClassAnalyzer::GetThisPublicMethods() const
  566. {
  567. vector<MethodAnalyzer> result;
  568. xml_node sectiondef = FindSectiondef(compounddef_, "public-func");
  569. for (xml_node memberdef : sectiondef.children("memberdef"))
  570. {
  571. MethodAnalyzer methodAnalyzer(*this, memberdef);
  572. result.push_back(methodAnalyzer);
  573. }
  574. return result;
  575. }
  576. vector<MethodAnalyzer> ClassAnalyzer::GetThisPublicStaticMethods() const
  577. {
  578. vector<MethodAnalyzer> result;
  579. xml_node sectiondef = FindSectiondef(compounddef_, "public-static-func");
  580. for (xml_node memberdef : sectiondef.children("memberdef"))
  581. {
  582. MethodAnalyzer methodAnalyzer(*this, memberdef);
  583. result.push_back(methodAnalyzer);
  584. }
  585. return result;
  586. }
  587. vector<FieldAnalyzer> ClassAnalyzer::GetAllFields() const
  588. {
  589. vector<FieldAnalyzer> result;
  590. vector<xml_node> memberdefs = GetMemberdefs();
  591. for (xml_node memberdef : memberdefs)
  592. {
  593. if (ExtractKind(memberdef) == "variable")
  594. result.push_back(FieldAnalyzer(*this, memberdef));
  595. }
  596. return result;
  597. }
  598. vector<FieldAnalyzer> ClassAnalyzer::GetThisPublicFields() const
  599. {
  600. vector<FieldAnalyzer> result;
  601. xml_node sectiondef = FindSectiondef(compounddef_, "public-attrib");
  602. for (xml_node memberdef : sectiondef.children("memberdef"))
  603. {
  604. FieldAnalyzer fieldAnalyzer(*this, memberdef);
  605. result.push_back(fieldAnalyzer);
  606. }
  607. return result;
  608. }
  609. vector<FieldAnalyzer> ClassAnalyzer::GetThisPublicStaticFields() const
  610. {
  611. vector<FieldAnalyzer> result;
  612. xml_node sectiondef = FindSectiondef(compounddef_, "public-static-attrib");
  613. for (xml_node memberdef : sectiondef.children("memberdef"))
  614. {
  615. FieldAnalyzer fieldAnalyzer(*this, memberdef);
  616. result.push_back(fieldAnalyzer);
  617. }
  618. return result;
  619. }
  620. bool ClassAnalyzer::ContainsMethod(const string& name) const
  621. {
  622. vector<MethodAnalyzer> methods = GetAllMethods();
  623. for (const MethodAnalyzer& method : methods)
  624. {
  625. if (method.GetName() == name)
  626. return true;
  627. }
  628. return false;
  629. }
  630. shared_ptr<MethodAnalyzer> ClassAnalyzer::GetMethod(const string& name) const
  631. {
  632. vector<MethodAnalyzer> methods = GetAllMethods();
  633. for (const MethodAnalyzer& method : methods)
  634. {
  635. if (method.GetName() == name)
  636. return make_shared<MethodAnalyzer>(method);
  637. }
  638. return nullptr;
  639. }
  640. int ClassAnalyzer::NumMethods(const string& name) const
  641. {
  642. int result = 0;
  643. vector<MethodAnalyzer> methods = GetAllMethods();
  644. for (const MethodAnalyzer& method : methods)
  645. {
  646. if (method.GetName() == name)
  647. result++;
  648. }
  649. return result;
  650. }
  651. bool ClassAnalyzer::IsAbstract() const
  652. {
  653. vector<MethodAnalyzer> methods = GetAllMethods();
  654. for (const MethodAnalyzer& method : methods)
  655. {
  656. if (method.IsPureVirtual())
  657. {
  658. if (!IsRefCounted())
  659. return true;
  660. // Some pure virtual functions is implemented by URHO3D_OBJECT
  661. string name = method.GetName();
  662. if (name == "GetType" || name == "GetTypeInfo" || name == "GetTypeName")
  663. {
  664. if (ContainsMethod("URHO3D_OBJECT"))
  665. continue;
  666. }
  667. return true;
  668. }
  669. }
  670. return false;
  671. }
  672. bool ClassAnalyzer::AllFloats() const
  673. {
  674. if (Contains(GetComment(), "ALL_FLOATS")) // TODO: remove
  675. return true;
  676. vector<FieldAnalyzer> fields = GetAllFields();
  677. for (const FieldAnalyzer& field : fields)
  678. {
  679. if (field.IsStatic())
  680. continue;
  681. string type = field.GetType().ToString();
  682. if (type != "float" && type != "double")
  683. return false;
  684. }
  685. return true;
  686. }
  687. bool ClassAnalyzer::AllInts() const
  688. {
  689. if (Contains(GetComment(), "ALL_INTS")) // TODO: remove
  690. return true;
  691. vector<FieldAnalyzer> fields = GetAllFields();
  692. for (const FieldAnalyzer& field : fields)
  693. {
  694. if (field.IsStatic())
  695. continue;
  696. string type = field.GetType().ToString();
  697. if (type != "int" && type != "unsigned")
  698. return false;
  699. }
  700. return true;
  701. }
  702. bool ClassAnalyzer::IsPod() const
  703. {
  704. bool result = Contains(GetComment(), "IS_POD");
  705. if (AllFloats() || AllInts())
  706. result = true;
  707. return result;
  708. }
  709. shared_ptr<ClassAnalyzer> ClassAnalyzer::GetBaseClass() const
  710. {
  711. xml_node basecompoundref = compounddef_.child("basecompoundref");
  712. if (!basecompoundref)
  713. return shared_ptr<ClassAnalyzer>();
  714. string refid = basecompoundref.attribute("refid").value();
  715. assert(!refid.empty());
  716. auto it = SourceData::classesByID_.find(refid);
  717. if (it == SourceData::classesByID_.end())
  718. return shared_ptr<ClassAnalyzer>();
  719. xml_node compounddef = it->second;
  720. return make_shared<ClassAnalyzer>(compounddef);
  721. }
  722. vector<ClassAnalyzer> ClassAnalyzer::GetBaseClasses() const
  723. {
  724. vector<ClassAnalyzer> result;
  725. for (xml_node basecompoundref : compounddef_.children("basecompoundref"))
  726. {
  727. string refid = basecompoundref.attribute("refid").value();
  728. if (refid.empty()) // Type from ThirdParty lib
  729. continue;
  730. auto it = SourceData::classesByID_.find(refid);
  731. if (it == SourceData::classesByID_.end())
  732. continue;
  733. xml_node compounddef = it->second;
  734. result.push_back(ClassAnalyzer(compounddef));
  735. }
  736. return result;
  737. }
  738. inline bool Contains(const vector<ClassAnalyzer>& classes, const ClassAnalyzer& cl)
  739. {
  740. for (const ClassAnalyzer& c : classes)
  741. {
  742. // Comparison without template specialization
  743. if (c.GetCompounddef() == cl.GetCompounddef())
  744. return true;
  745. }
  746. return false;
  747. }
  748. static void RecursivelyGetBaseClasses(const ClassAnalyzer& analyzer, vector<ClassAnalyzer>& result)
  749. {
  750. for (const ClassAnalyzer& baseClass : analyzer.GetBaseClasses())
  751. {
  752. if (!Contains(result, baseClass))
  753. result.push_back(baseClass);
  754. RecursivelyGetBaseClasses(baseClass, result);
  755. }
  756. }
  757. vector<ClassAnalyzer> ClassAnalyzer::GetAllBaseClasses() const
  758. {
  759. vector<ClassAnalyzer> result;
  760. RecursivelyGetBaseClasses(*this, result);
  761. return result;
  762. }
  763. vector<ClassAnalyzer> ClassAnalyzer::GetDerivedClasses() const
  764. {
  765. vector<ClassAnalyzer> result;
  766. for (xml_node basecompoundref : compounddef_.children("derivedcompoundref"))
  767. {
  768. string refid = basecompoundref.attribute("refid").value();
  769. if (refid.empty()) // Type from ThirdParty lib
  770. continue;
  771. auto it = SourceData::classesByID_.find(refid);
  772. if (it == SourceData::classesByID_.end())
  773. continue;
  774. xml_node compounddef = it->second;
  775. result.push_back(ClassAnalyzer(compounddef));
  776. }
  777. return result;
  778. }
  779. static void RecursivelyGetDerivedClasses(const ClassAnalyzer& analyzer, vector<ClassAnalyzer>& result)
  780. {
  781. for (const ClassAnalyzer& derivedClass : analyzer.GetDerivedClasses())
  782. {
  783. if (!Contains(result, derivedClass))
  784. result.push_back(derivedClass);
  785. RecursivelyGetDerivedClasses(derivedClass, result);
  786. }
  787. }
  788. vector<ClassAnalyzer> ClassAnalyzer::GetAllDerivedClasses() const
  789. {
  790. vector<ClassAnalyzer> result;
  791. RecursivelyGetDerivedClasses(*this, result);
  792. return result;
  793. }
  794. bool ClassAnalyzer::HasThisConstructor() const
  795. {
  796. vector<MethodAnalyzer> methods = GetAllMethods();
  797. for (const MethodAnalyzer& method : methods)
  798. {
  799. if (method.IsThisConstructor())
  800. return true;
  801. }
  802. return false;
  803. }
  804. bool ClassAnalyzer::IsRefCounted() const
  805. {
  806. if (GetClassName() == "RefCounted")
  807. return true;
  808. vector<ClassAnalyzer> baseClasses = GetAllBaseClasses();
  809. for (const ClassAnalyzer& classAnalyzer : baseClasses)
  810. {
  811. if (classAnalyzer.GetClassName() == "RefCounted")
  812. return true;
  813. }
  814. return false;
  815. }
  816. shared_ptr<MethodAnalyzer> ClassAnalyzer::GetDefinedThisDefaultConstructor() const
  817. {
  818. vector<MethodAnalyzer> methods = GetAllMethods();
  819. for (const MethodAnalyzer& method : methods)
  820. {
  821. if (method.IsThisDefaultConstructor())
  822. return make_shared<MethodAnalyzer>(method);
  823. }
  824. return nullptr;
  825. }
  826. vector<MethodAnalyzer> ClassAnalyzer::GetThisNonDefaultConstructors() const
  827. {
  828. vector<MethodAnalyzer> result;
  829. vector<MethodAnalyzer> methods = GetAllMethods();
  830. for (const MethodAnalyzer& method : methods)
  831. {
  832. if (method.IsThisNonDefaultConstructor())
  833. result.push_back(method);
  834. }
  835. return result;
  836. }
  837. // ============================================================================
  838. FunctionAnalyzer::FunctionAnalyzer(xml_node memberdef, const TemplateSpecialization& specialization)
  839. : memberdef_(memberdef)
  840. , specialization_(specialization)
  841. {
  842. assert(IsMemberdef(memberdef));
  843. assert(ExtractKind(memberdef) == "function");
  844. }
  845. // ============================================================================
  846. MethodAnalyzer::MethodAnalyzer(const ClassAnalyzer& classAnalyzer, xml_node memberdef, const TemplateSpecialization& specialization)
  847. : FunctionAnalyzer(memberdef, specialization)
  848. , classAnalyzer_(classAnalyzer)
  849. {
  850. // Append template specialization from class
  851. specialization_.insert(classAnalyzer.GetSpecialization().begin(), classAnalyzer.GetSpecialization().end());
  852. }
  853. string MethodAnalyzer::GetVirt() const
  854. {
  855. string result = memberdef_.attribute("virt").value();
  856. assert(!result.empty());
  857. return result;
  858. }
  859. string MethodAnalyzer::GetContainsClassName() const
  860. {
  861. string argsstring = ExtractArgsstring(memberdef_);
  862. assert(!argsstring.empty());
  863. string prototype = ExtractDefinition(memberdef_) + argsstring;
  864. smatch match;
  865. regex_match(prototype, match, regex(".*Urho3D::(.+?)::.*"));
  866. assert(match.size());
  867. string result = match[1].str();
  868. return result;
  869. }
  870. /*
  871. string FieldAnalyzer::GetDeclaration() const
  872. {
  873. string definition = ExtractDefinition(memberdef_);
  874. assert(!definition.empty());
  875. // Remove Urho3D::
  876. smatch match;
  877. regex_match(definition, match, regex("(.*)Urho3D::(.+)"));
  878. assert(match.size() == 3);
  879. string result = match[1].str() + match[2].str();
  880. result = BeautifyDefinition(result);
  881. return result;
  882. }
  883. */
  884. string GetVariableDeclaration(xml_node memberdef)
  885. {
  886. assert(IsMemberdef(memberdef));
  887. assert(ExtractKind(memberdef) == "variable");
  888. string result = ExtractDefinition(memberdef);
  889. result = RemoveFirst(result, "URHO3D_API ");
  890. result = RemoveFirst(result, " URHO3D_API");
  891. assert(Contains(result, " Urho3D::"));
  892. result = ReplaceFirst(result, " Urho3D::", " ");
  893. if (IsStatic(memberdef))
  894. result = "static " + result;
  895. result = BeautifyDefinition(result);
  896. return result;
  897. }
  898. string GetFunctionDeclaration(xml_node memberdef)
  899. {
  900. assert(IsMemberdef(memberdef));
  901. assert(ExtractKind(memberdef) == "function");
  902. string argsstring = ExtractArgsstring(memberdef);
  903. assert(!argsstring.empty());
  904. string prototype = ExtractDefinition(memberdef) + argsstring;
  905. smatch match;
  906. regex_match(prototype, match, regex("([^(]*)Urho3D::(.+?)"));
  907. assert(match.size());
  908. string result = match[1].str() + match[2].str();
  909. if (IsExplicit(memberdef))
  910. result = "explicit " + result;
  911. if (IsTemplate(memberdef))
  912. {
  913. string t = "";
  914. xml_node templateparamlist = memberdef.child("templateparamlist");
  915. for (xml_node param : templateparamlist.children("param"))
  916. {
  917. if (t.length() > 0)
  918. t += ", ";
  919. xml_node type = param.child("type");
  920. assert(type);
  921. t += type.child_value();
  922. xml_node declname = param.child("declname");
  923. if (!declname.empty())
  924. t += " " + string(declname.child_value());
  925. }
  926. result = "template<" + t + "> " + result;
  927. }
  928. result = RemoveFirst(result, "URHO3D_API ");
  929. result = RemoveFirst(result, " URHO3D_API");
  930. result = BeautifyDefinition(result);
  931. return result;
  932. }
  933. string GetFunctionLocation(xml_node memberdef)
  934. {
  935. return GetFunctionDeclaration(memberdef) + " | File: " + ExtractHeaderFile(memberdef);
  936. }
  937. bool MethodAnalyzer::IsConst() const
  938. {
  939. string constAttr = memberdef_.attribute("const").value();
  940. assert(!constAttr.empty());
  941. return constAttr == "yes";
  942. }
  943. bool MethodAnalyzer::CanBeGetProperty() const
  944. {
  945. string returnType = GetReturnType().ToString();
  946. if (returnType == "void" || returnType.empty())
  947. return false;
  948. if (GetParams().size() != 0 && GetParams().size() != 1)
  949. return false;
  950. return true;
  951. }
  952. bool MethodAnalyzer::CanBeSetProperty() const
  953. {
  954. string returnType = GetReturnType().ToString();
  955. if (returnType != "void")
  956. return false;
  957. if (GetParams().size() != 1 && GetParams().size() != 2)
  958. return false;
  959. return true;
  960. }
  961. bool MethodAnalyzer::IsParentDestructor() const
  962. {
  963. string functionName = GetName();
  964. if (!StartsWith(functionName, "~"))
  965. return false;
  966. return !IsThisDestructor();
  967. }
  968. bool MethodAnalyzer::IsConstructor() const
  969. {
  970. string name = GetName();
  971. return ExtractDefinition(memberdef_) == "Urho3D::" + name + "::" + name;
  972. }
  973. bool MethodAnalyzer::IsDestructor() const
  974. {
  975. string name = GetName();
  976. return StartsWith(name, "~");
  977. }
  978. bool MethodAnalyzer::IsParentConstructor() const
  979. {
  980. if (IsThisConstructor())
  981. return false;
  982. string name = GetName();
  983. return ExtractDefinition(memberdef_) == "Urho3D::" + name + "::" + name;
  984. }
  985. shared_ptr<MethodAnalyzer> MethodAnalyzer::Reimplements() const
  986. {
  987. xml_node reimplements = memberdef_.child("reimplements");
  988. if (!reimplements)
  989. return shared_ptr<MethodAnalyzer>();
  990. string refid = reimplements.attribute("refid").value();
  991. assert(!refid.empty());
  992. auto it = SourceData::members_.find(refid);
  993. if (it == SourceData::members_.end())
  994. return shared_ptr<MethodAnalyzer>();
  995. xml_node memberdef = it->second;
  996. return make_shared<MethodAnalyzer>(classAnalyzer_, memberdef);
  997. }
  998. // ============================================================================
  999. FieldAnalyzer::FieldAnalyzer(ClassAnalyzer classAnalyzer, xml_node memberdef)
  1000. : classAnalyzer_(classAnalyzer)
  1001. , memberdef_(memberdef)
  1002. {
  1003. assert(IsMemberdef(memberdef));
  1004. assert(ExtractKind(memberdef) == "variable");
  1005. }
  1006. string FieldAnalyzer::GetLocation() const
  1007. {
  1008. string result = GetDeclaration();
  1009. result += " | File: " + GetHeaderFile();
  1010. if (!classAnalyzer_.usingLocation_.empty())
  1011. result = classAnalyzer_.usingLocation_ + " | " + result;
  1012. return result;
  1013. }
  1014. // ============================================================================
  1015. NamespaceAnalyzer::NamespaceAnalyzer(xml_node compounddef)
  1016. : compounddef_(compounddef)
  1017. {
  1018. assert(IsCompounddef(compounddef));
  1019. assert(ExtractKind(compounddef) == "namespace");
  1020. }
  1021. vector<EnumAnalyzer> NamespaceAnalyzer::GetEnums()
  1022. {
  1023. xml_node sectiondef = FindSectiondef(compounddef_, "enum");
  1024. assert(sectiondef);
  1025. vector<EnumAnalyzer> result;
  1026. for (xml_node memberdef : sectiondef.children("memberdef"))
  1027. {
  1028. EnumAnalyzer analyzer(memberdef);
  1029. result.push_back(analyzer);
  1030. }
  1031. return result;
  1032. }
  1033. vector<GlobalVariableAnalyzer> NamespaceAnalyzer::GetVariables()
  1034. {
  1035. xml_node sectiondef = FindSectiondef(compounddef_, "var");
  1036. assert(sectiondef);
  1037. vector<GlobalVariableAnalyzer> result;
  1038. for (xml_node memberdef : sectiondef.children("memberdef"))
  1039. result.push_back(GlobalVariableAnalyzer(memberdef));
  1040. return result;
  1041. }
  1042. vector<GlobalFunctionAnalyzer> NamespaceAnalyzer::GetFunctions()
  1043. {
  1044. xml_node sectiondef = FindSectiondef(compounddef_, "func");
  1045. assert(sectiondef);
  1046. vector<GlobalFunctionAnalyzer> result;
  1047. for (xml_node memberdef : sectiondef.children("memberdef"))
  1048. result.push_back(GlobalFunctionAnalyzer(memberdef));
  1049. return result;
  1050. }
  1051. // ============================================================================
  1052. UsingAnalyzer::UsingAnalyzer(xml_node memberdef)
  1053. : memberdef_(memberdef)
  1054. {
  1055. assert(IsMemberdef(memberdef));
  1056. assert(ExtractKind(memberdef) == "typedef");
  1057. }
  1058. // ============================================================================
  1059. GlobalFunctionAnalyzer::GlobalFunctionAnalyzer(xml_node memberdef, const TemplateSpecialization& specialization)
  1060. : FunctionAnalyzer(memberdef, specialization)
  1061. {
  1062. }
  1063. // ============================================================================
  1064. ClassStaticFunctionAnalyzer::ClassStaticFunctionAnalyzer(const ClassAnalyzer& classAnalyzer, xml_node memberdef, const TemplateSpecialization& specialization)
  1065. : FunctionAnalyzer(memberdef, specialization)
  1066. , classAnalyzer_(classAnalyzer)
  1067. {
  1068. assert(IsStatic(memberdef));
  1069. }