XmlAnalyzer.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include <PugiXml/pugixml.hpp>
  5. #include <string>
  6. #include <memory>
  7. #include <vector>
  8. #include <map>
  9. #include "XmlSourceData.h"
  10. #include "Utils.h"
  11. using TemplateSpecialization = std::map<std::string, std::string>;
  12. // <type>...</type> | <defval>...</defval> | <para>...</para>
  13. std::string RemoveRefs(pugi::xml_node node);
  14. // <type>...</type>
  15. class TypeAnalyzer
  16. {
  17. private:
  18. std::string fullType_;
  19. std::string name_;
  20. bool isConst_;
  21. bool isConstexpr_;
  22. bool isPointer_; // *
  23. bool isReference_; // &
  24. bool isRvalueReference_; // &&
  25. bool isDoublePointer_; // **
  26. bool isRefToPoiner_; // *&
  27. std::string templateParams_;
  28. public:
  29. TypeAnalyzer(pugi::xml_node type, const TemplateSpecialization& specialization = {});
  30. // Used for doxygen bug workaround https://github.com/doxygen/doxygen/issues/7732
  31. TypeAnalyzer(const std::string& typeName);
  32. std::string ToString() const { return fullType_; }
  33. std::string GetName() const { return name_; }
  34. bool IsConst() const { return isConst_; }
  35. bool IsConstexpr() const { return isConstexpr_; }
  36. bool IsPointer() const { return isPointer_; }
  37. bool IsReference() const { return isReference_; }
  38. bool IsRvalueReference() const { return isRvalueReference_; }
  39. bool IsDoublePointer() const { return isDoublePointer_; }
  40. bool IsRefToPointer() const { return isRefToPoiner_; }
  41. bool IsTemplate() const { return templateParams_.length() > 0; }
  42. std::string GetTemplateParams() { return templateParams_; }
  43. std::string GetNameWithTemplateParams() const { return IsTemplate() ? name_ + "<" + templateParams_ + ">" : name_; }
  44. };
  45. // <memberdef kind="function">
  46. // <param>...</param>
  47. class ParamAnalyzer
  48. {
  49. private:
  50. pugi::xml_node node_;
  51. TemplateSpecialization specialization_;
  52. public:
  53. ParamAnalyzer(pugi::xml_node param, const TemplateSpecialization& specialization = {});
  54. pugi::xml_node GetNode() const { return node_; }
  55. std::string ToString() const;
  56. // <param>
  57. // <type>....</type>
  58. TypeAnalyzer GetType() const;
  59. // <param>
  60. // <declname>....</declname>
  61. std::string GetDeclname() const;
  62. // <param>
  63. // <defval>....</defval>
  64. std::string GetDefval() const; // Default value
  65. };
  66. // <memberdef>
  67. inline bool IsMemberdef(pugi::xml_node node) { return node.name() == std::string("memberdef"); }
  68. // <compounddef>
  69. inline bool IsCompounddef(pugi::xml_node node) { return node.name() == std::string("compounddef"); }
  70. // <member>
  71. inline bool IsMember(pugi::xml_node node) { return node.name() == std::string("member"); }
  72. // <sectiondef>
  73. inline bool IsSectiondef(pugi::xml_node node) { return node.name() == std::string("sectiondef"); }
  74. // <enumvalue>
  75. inline bool IsEnumvalue(pugi::xml_node node) { return node.name() == std::string("enumvalue"); }
  76. // <compounddef>
  77. // <compoundname>...</compoundname>
  78. std::string ExtractCompoundname(pugi::xml_node compounddef);
  79. // <compounddef>
  80. // <sectiondef kind="xxx">...</sectiondef>
  81. pugi::xml_node FindSectiondef(pugi::xml_node compounddef, const std::string& kind);
  82. // <memberdef static="yes">
  83. bool IsStatic(pugi::xml_node memberdef);
  84. // <memberdef kind="function" explicit="yes">
  85. bool IsExplicit(pugi::xml_node memberdef);
  86. // <memberdef>
  87. // <definition>...</definition>
  88. std::string ExtractDefinition(pugi::xml_node memberdef);
  89. // <memberdef>
  90. // <argsstring>...</argsstring>
  91. std::string ExtractArgsstring(pugi::xml_node memberdef);
  92. // <memberdef kind="function">
  93. // <argsstring>(...)</argsstring>
  94. // <argsstring>(...) xxx</argsstring>
  95. // where xxx can be of const, override, =default, =delete, =0 or their combination
  96. std::string ExtractCleanedFunctionArgsstring(pugi::xml_node memberdef);
  97. // <memberdef prot="...">
  98. std::string ExtractProt(pugi::xml_node memberdef);
  99. // <memberdef>
  100. // <type>...</type>
  101. TypeAnalyzer ExtractType(pugi::xml_node memberdef, const TemplateSpecialization& specialization = {});
  102. // <memberdef kind="function">
  103. // <param>...</param>
  104. // <param>...</param>
  105. std::vector<ParamAnalyzer> ExtractParams(pugi::xml_node memberdef, const TemplateSpecialization& specialization = {});
  106. // <memberdef kind="function">
  107. // <param>...</param>
  108. // <param>...</param>
  109. std::string JoinParamsTypes(pugi::xml_node memberdef, const TemplateSpecialization& specialization = {});
  110. std::string JoinParamsNames(pugi::xml_node memberdef, bool skipContext = false);
  111. // <memberdef kind="function">
  112. // ...
  113. std::string GetFunctionDeclaration(pugi::xml_node memberdef);
  114. // <memberdef kind="variable">
  115. // ...
  116. std::string GetVariableDeclaration(pugi::xml_node memberdef);
  117. // <memberdef kind="function">
  118. // ...
  119. std::string GetFunctionLocation(pugi::xml_node memberdef);
  120. // <compounddef|memberdef id="...">
  121. std::string ExtractID(pugi::xml_node node);
  122. // <compounddef|memberdef|member|sectiondef kind="...">
  123. std::string ExtractKind(pugi::xml_node node);
  124. // <memberdef|enumvalue>
  125. // <name>...</name>
  126. std::string ExtractName(pugi::xml_node node);
  127. // <compounddef|memberdef>
  128. // <location line="...">
  129. std::string ExtractLine(pugi::xml_node node);
  130. // <compounddef|memberdef>
  131. // <location column="...">
  132. std::string ExtractColumn(pugi::xml_node node);
  133. // <compounddef|memberdef>
  134. // <briefdescription>...</briefdescription>
  135. // <detaileddescription>...</detaileddescription>
  136. std::string ExtractComment(pugi::xml_node node);
  137. // <compounddef|memberdef>
  138. // <location ...>
  139. // Extract header file path and convert to relative.
  140. // Return empty std::string when declared in *.cpp
  141. std::string ExtractHeaderFile(pugi::xml_node node);
  142. // <compounddef|memberdef>
  143. // <templateparamlist>
  144. bool IsTemplate(pugi::xml_node node);
  145. // <compounddef|memberdef>
  146. // <templateparamlist>
  147. // <param>...</param>
  148. // <param>...</param>
  149. std::vector<std::string> ExtractTemplateParams(pugi::xml_node node);
  150. // <compounddef kind="namespace">
  151. // <sectiondef kind="enum">
  152. // <memberdef kind="enum">...</memberdef>
  153. class EnumAnalyzer
  154. {
  155. pugi::xml_node memberdef_;
  156. public:
  157. EnumAnalyzer(pugi::xml_node memberdef);
  158. std::string GetTypeName() const { return ExtractName(memberdef_); }
  159. std::string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
  160. std::string GetComment() const { return ExtractComment(memberdef_); }
  161. bool IsInternal() const { return GetHeaderFile().empty(); } // true if declared in .cpp file
  162. std::string GetBaseType() const;
  163. std::string GetLocation() const;
  164. bool IsClass() const;
  165. // <memberdef kind="enum">
  166. // <enumvalue><name>...</name></enumvalue>
  167. // <enumvalue><name>...</name></enumvalue>
  168. std::vector<std::string> GetEnumerators() const;
  169. };
  170. // <compounddef kind="namespace">
  171. // <sectiondef kind="var">
  172. // <memberdef kind="variable">...</memberdef>
  173. class GlobalVariableAnalyzer
  174. {
  175. pugi::xml_node memberdef_;
  176. public:
  177. GlobalVariableAnalyzer(pugi::xml_node memberdef);
  178. std::string GetName() const { return ExtractName(memberdef_); }
  179. std::string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
  180. std::string GetComment() const { return ExtractComment(memberdef_); }
  181. bool IsStatic() const { return ::IsStatic(memberdef_); }
  182. TypeAnalyzer GetType() const { return ExtractType(memberdef_); }
  183. bool IsArray() const { return StartsWith(ExtractArgsstring(memberdef_), "["); }
  184. std::string GetLocation() const { return GetVariableDeclaration(memberdef_) + " | File: " + GetHeaderFile(); }
  185. };
  186. class MethodAnalyzer;
  187. class FieldAnalyzer;
  188. // <compounddef kind="class|struct">...</compounddef>
  189. class ClassAnalyzer
  190. {
  191. private:
  192. pugi::xml_node compounddef_;
  193. TemplateSpecialization specialization_;
  194. std::vector<pugi::xml_node> GetMemberdefs() const;
  195. public:
  196. std::string usingLocation_;
  197. pugi::xml_node GetCompounddef() const { return compounddef_; }
  198. ClassAnalyzer(pugi::xml_node compounddef, const TemplateSpecialization& specialization = {});
  199. const TemplateSpecialization& GetSpecialization() const { return specialization_; }
  200. std::string GetClassName() const;
  201. std::string GetComment() const { return ExtractComment(compounddef_); }
  202. std::string GetHeaderFile() const { return ExtractHeaderFile(compounddef_); }
  203. std::string GetDirName() const;
  204. std::string GetKind() const { return ExtractKind(compounddef_); }
  205. bool IsInternal() const;
  206. bool IsTemplate() const { return ::IsTemplate(compounddef_); }
  207. std::vector<MethodAnalyzer> GetAllMethods() const;
  208. std::vector<MethodAnalyzer> GetAllPublicMethods() const;
  209. std::vector<MethodAnalyzer> GetThisPublicMethods() const;
  210. std::vector<MethodAnalyzer> GetThisPublicStaticMethods() const;
  211. std::vector<FieldAnalyzer> GetAllFields() const;
  212. std::vector<FieldAnalyzer> GetThisPublicFields() const;
  213. std::vector<FieldAnalyzer> GetThisPublicStaticFields() const;
  214. bool ContainsMethod(const std::string& name) const;
  215. std::shared_ptr<MethodAnalyzer> GetMethod(const std::string& name) const;
  216. int NumMethods(const std::string& name) const;
  217. bool IsRefCounted() const;
  218. bool HasThisDestructor() const { return ContainsMethod("~" + GetClassName()); }
  219. bool HasThisConstructor() const;
  220. bool IsAbstract() const;
  221. std::string GetLocation() const { return GetKind() + " " + GetClassName() + " | File: " + GetHeaderFile(); }
  222. bool AllFloats() const;
  223. bool AllInts() const;
  224. bool IsPod() const;
  225. bool IsNoCount() const { return Contains(GetComment(), "NO_COUNT"); } // Have @nocount in comment -> asOBJ_NOCOUNT
  226. std::shared_ptr<ClassAnalyzer> GetBaseClass() const;
  227. std::vector<ClassAnalyzer> GetBaseClasses() const;
  228. std::vector<ClassAnalyzer> GetAllBaseClasses() const;
  229. std::vector<ClassAnalyzer> GetDerivedClasses() const;
  230. std::vector<ClassAnalyzer> GetAllDerivedClasses() const;
  231. // Return null if default constructor is implicitly-declared.
  232. // Return pointer if default constructor is deleted
  233. std::shared_ptr<MethodAnalyzer> GetDefinedThisDefaultConstructor() const;
  234. std::vector<MethodAnalyzer> GetThisNonDefaultConstructors() const;
  235. // Return null if destructor is implicitly-declared.
  236. // Return pointer if destructor is deleted
  237. std::shared_ptr<MethodAnalyzer> GetDefinedThisDestructor() const { return GetMethod("~" + GetClassName()); }
  238. int GetInherianceDeep(int counter = 0) const;
  239. std::vector<std::string> GetAllPublicMembersRefids() const;
  240. // Base class members that were hidden in this class (c++ declarations)
  241. std::vector<std::string> GetHiddenMethods() const;
  242. std::vector<std::string> GetHiddenStaticMethods() const;
  243. std::vector<std::string> GetHiddenFields() const;
  244. std::vector<std::string> GetHiddenStaticFields() const;
  245. };
  246. // <memberdef kind="function">...</memberdef>
  247. class FunctionAnalyzer
  248. {
  249. protected:
  250. pugi::xml_node memberdef_;
  251. TemplateSpecialization specialization_;
  252. public:
  253. FunctionAnalyzer(pugi::xml_node memberdef, const TemplateSpecialization& specialization = {});
  254. pugi::xml_node GetMemberdef() const { return memberdef_; }
  255. const TemplateSpecialization& GetSpecialization() const { return specialization_; }
  256. std::string GetComment() const { return ExtractComment(memberdef_); }
  257. std::string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
  258. std::string GetName() const { return ExtractName(memberdef_); }
  259. std::vector<ParamAnalyzer> GetParams() const { return ExtractParams(memberdef_, specialization_); }
  260. TypeAnalyzer GetReturnType() const { return ExtractType(memberdef_, specialization_); }
  261. std::vector<std::string> GetTemplateParams() const { return ExtractTemplateParams(memberdef_); }
  262. bool IsDefine() const { return CONTAINS(SourceData::defines_, GetName()); }
  263. bool IsTemplate() const { return ::IsTemplate(memberdef_); }
  264. std::string JoinParamsNames(bool skipContext = false) const { return ::JoinParamsNames(memberdef_, skipContext); } // TODO убрать skipContext, он больше не нужен
  265. std::string JoinParamsTypes() const { return ::JoinParamsTypes(memberdef_, specialization_); }
  266. virtual std::string GetLocation() const { return GetFunctionLocation(memberdef_); }
  267. };
  268. // <compounddef kind="class|struct">
  269. // <sectiondef>
  270. // <memberdef kind="function">...</memberdef>
  271. class MethodAnalyzer : public FunctionAnalyzer
  272. {
  273. ClassAnalyzer classAnalyzer_;
  274. public:
  275. MethodAnalyzer(const ClassAnalyzer& classAnalyzer, pugi::xml_node memberdef, const TemplateSpecialization& specialization = {});
  276. ClassAnalyzer GetClass() const { return classAnalyzer_; }
  277. // <memberdef kind="function" virt="...">
  278. std::string GetVirt() const;
  279. bool IsPureVirtual() const { return GetVirt() == "pure-virtual"; }
  280. // <memberdef kind="function" const="yes">
  281. bool IsConst() const;
  282. // <memberdef>
  283. // <reimplements refid="..."></reimplements>
  284. std::shared_ptr<MethodAnalyzer> Reimplements() const;
  285. std::string GetClassName() const { return classAnalyzer_.GetClassName(); }
  286. std::string GetContainsClassName() const; // May this function defined in parent class, so return name oа class, real define this function
  287. bool IsStatic() const { return ::IsStatic(memberdef_); }
  288. bool IsPublic() const { return ExtractProt(memberdef_) == "public"; }
  289. // Constructor can have different name https://github.com/doxygen/doxygen/issues/8402
  290. bool IsThisConstructor() const { return GetName() == GetClassName(); }
  291. bool IsThisDefaultConstructor() const { return IsThisConstructor() && ExtractCleanedFunctionArgsstring(memberdef_).empty(); }
  292. bool IsThisNonDefaultConstructor() const { return IsThisConstructor() && !ExtractCleanedFunctionArgsstring(memberdef_).empty(); }
  293. bool IsConstructor() const;
  294. bool IsDestructor() const;
  295. bool IsParentConstructor() const;
  296. bool IsThisDestructor() const { return GetName() == "~" + GetClassName(); }
  297. bool IsParentDestructor() const;
  298. bool CanBeGetProperty() const;
  299. bool CanBeSetProperty() const;
  300. bool IsExplicit() const { return ::IsExplicit(memberdef_); }
  301. bool IsDeleted() const { return EndsWith(ExtractArgsstring(memberdef_), "=delete"); }
  302. bool IsConsversionOperator() const { return StartsWith(GetName(), "operator "); }
  303. bool IsThisMethod() const { return GetContainsClassName() == GetClassName(); } // Defined in this class
  304. bool IsPrefixIncrementOperator() const { return GetName() == "operator++" && GetParams().size() == 0; }
  305. bool IsPostfixIncrementOperator() const { return GetName() == "operator++" && GetParams().size() != 0; }
  306. bool IsPrefixDecrementOperator() const { return GetName() == "operator--" && GetParams().size() == 0; }
  307. bool IsPostfixDecrementOperator() const { return GetName() == "operator--" && GetParams().size() != 0; }
  308. std::string GetDeclaration() const { return JoinNonEmpty({ classAnalyzer_.usingLocation_, GetFunctionDeclaration(memberdef_) }, " | "); }
  309. std::string GetLocation() const override { return JoinNonEmpty({ classAnalyzer_.usingLocation_, GetFunctionLocation(memberdef_) }, " | "); }
  310. };
  311. // <compounddef kind="class|struct">
  312. // <sectiondef>
  313. // <memberdef kind="variable">...</memberdef>
  314. class FieldAnalyzer
  315. {
  316. ClassAnalyzer classAnalyzer_;
  317. pugi::xml_node memberdef_;
  318. public:
  319. FieldAnalyzer(ClassAnalyzer classAnalyzer, pugi::xml_node memberdef);
  320. bool IsStatic() const { return ::IsStatic(memberdef_); }
  321. TypeAnalyzer GetType() const { return ExtractType(memberdef_); }
  322. std::string GetName() const { return ExtractName(memberdef_); }
  323. std::string GetComment() const { return ExtractComment(memberdef_); }
  324. bool IsPublic() const { return ExtractProt(memberdef_) == "public"; }
  325. std::string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
  326. std::string GetDeclaration() const { return GetVariableDeclaration(memberdef_); }
  327. std::string GetLocation() const;
  328. std::string GetClassName() const { return classAnalyzer_.GetClassName(); }
  329. bool IsArray() const { return StartsWith(ExtractArgsstring(memberdef_), "["); };
  330. };
  331. // <compounddef kind="namespace">
  332. // <sectiondef kind="func">
  333. // <memberdef kind="function">...</memberdef>
  334. class GlobalFunctionAnalyzer : public FunctionAnalyzer
  335. {
  336. public:
  337. GlobalFunctionAnalyzer(pugi::xml_node memberdef, const TemplateSpecialization& specialization = {});
  338. };
  339. // <compounddef kind="class|struct">
  340. // <sectiondef kind="public-static-func">
  341. // <memberdef kind="function" prot="public" static="yes">...</memberdef>
  342. class ClassStaticFunctionAnalyzer : public FunctionAnalyzer
  343. {
  344. ClassAnalyzer classAnalyzer_;
  345. public:
  346. ClassStaticFunctionAnalyzer(const ClassAnalyzer& classAnalyzer, pugi::xml_node memberdef, const TemplateSpecialization& specialization = {});
  347. std::string GetClassName() const { return classAnalyzer_.GetClassName(); }
  348. };
  349. // <memberdef kind="typedef">
  350. // <definition>using ...</definition>
  351. class UsingAnalyzer
  352. {
  353. private:
  354. pugi::xml_node memberdef_;
  355. public:
  356. UsingAnalyzer(pugi::xml_node memberdef);
  357. std::string GetComment() const { return ExtractComment(memberdef_); }
  358. std::string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
  359. std::string GetLocation() const { return "using " + GetName() + " = " + GetType().ToString() + " | File: " + GetHeaderFile(); }
  360. std::string GetName() const { return ExtractName(memberdef_); }
  361. TypeAnalyzer GetType() const { return ExtractType(memberdef_); }
  362. };
  363. // <compounddef kind = "namespace">...</compounddef>
  364. class NamespaceAnalyzer
  365. {
  366. private:
  367. pugi::xml_node compounddef_;
  368. public:
  369. NamespaceAnalyzer(pugi::xml_node compounddef);
  370. // <compounddef kind="namespace">
  371. // <sectiondef kind="enum">
  372. // <memberdef kind="enum">...</memberdef>
  373. // <memberdef kind="enum">...</memberdef>
  374. std::vector<EnumAnalyzer> GetEnums();
  375. // <compounddef kind="namespace">
  376. // <sectiondef kind="var">
  377. // <memberdef kind="variable">...</memberdef>
  378. // <memberdef kind="variable">...</memberdef>
  379. std::vector<GlobalVariableAnalyzer> GetVariables();
  380. // <compounddef kind="namespace">
  381. // <sectiondef kind="func">
  382. // <memberdef kind="function">...</memberdef>
  383. // <memberdef kind="function">...</memberdef>
  384. std::vector<GlobalFunctionAnalyzer> GetFunctions();
  385. };