XmlAnalyzer.h 19 KB

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