ASResult.cpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  1. //
  2. // Copyright (c) 2008-2021 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 "ASResult.h"
  23. #include "Tuning.h"
  24. #include "Utils.h"
  25. #include <fstream>
  26. #include <cassert>
  27. #include <unordered_map>
  28. #include <memory>
  29. extern string _sourceDir;
  30. namespace ASBindingGenerator
  31. {
  32. ASGeneratedFile_WithRegistrationFunction::ASGeneratedFile_WithRegistrationFunction(const string& outputFilePath, const string& functionName)
  33. {
  34. outputFilePath_ = outputFilePath;
  35. functionName_ = functionName;
  36. }
  37. // ============================================================================
  38. void ASGeneratedFile_Members::Save()
  39. {
  40. ofstream out(outputFilePath_);
  41. out <<
  42. "// DO NOT EDIT. This file is generated\n"
  43. "\n"
  44. "#include \"../Precompiled.h\"\n"
  45. "#include \"../AngelScript/APITemplates.h\"\n"
  46. "\n"
  47. "#include \"../AngelScript/Generated_Includes.h\"\n"
  48. "#include \"../AngelScript/Manual.h\"\n"
  49. "\n"
  50. "namespace Urho3D\n"
  51. "{\n"
  52. "\n"
  53. "void FakeAddRef(void* ptr);\n"
  54. "void FakeReleaseRef(void* ptr);\n"
  55. "\n"
  56. << glue_.str() <<
  57. "void " << functionName_ << "(asIScriptEngine* engine)\n"
  58. "{\n"
  59. << reg_.str() <<
  60. "}\n"
  61. "\n"
  62. "}\n";
  63. }
  64. // ============================================================================
  65. ASGeneratedFile_Templates::ASGeneratedFile_Templates(const string& outputFilePath)
  66. {
  67. outputFilePath_ = outputFilePath;
  68. }
  69. void ASGeneratedFile_Templates::Save()
  70. {
  71. ofstream out(outputFilePath_);
  72. out <<
  73. "// DO NOT EDIT. This file is generated\n"
  74. "\n"
  75. "#pragma once\n"
  76. "\n"
  77. "#include \"../Precompiled.h\"\n"
  78. "#include \"../AngelScript/APITemplates.h\"\n"
  79. "\n"
  80. "#include \"../AngelScript/Generated_Includes.h\"\n"
  81. "\n"
  82. "#include \"../AngelScript/Manual.h\"\n"
  83. "\n"
  84. "namespace Urho3D\n"
  85. "{\n"
  86. "\n"
  87. "void FakeAddRef(void* ptr);\n"
  88. "void FakeReleaseRef(void* ptr);\n"
  89. "\n"
  90. << glue_.str()
  91. << reg_.str() <<
  92. "}\n";
  93. }
  94. bool ProcessedEnum::operator <(const ProcessedEnum& rhs) const
  95. {
  96. if (insideDefine_ != rhs.insideDefine_)
  97. return insideDefine_ < rhs.insideDefine_;
  98. return name_ < rhs.name_;
  99. }
  100. bool ProcessedGlobalFunction::operator <(const ProcessedGlobalFunction& rhs) const
  101. {
  102. if (insideDefine_ != rhs.insideDefine_)
  103. return insideDefine_ < rhs.insideDefine_;
  104. if (name_ != rhs.name_)
  105. return name_ < rhs.name_;
  106. // Overloads with the same name may exist
  107. if (comment_ != rhs.comment_)
  108. return comment_ < rhs.comment_;
  109. // Different specializations of the same template and aliases have the same comment
  110. return registration_ < rhs.registration_;
  111. }
  112. bool ProcessedGlobalVariable::operator <(const ProcessedGlobalVariable& rhs) const
  113. {
  114. if (insideDefine_ != rhs.insideDefine_)
  115. return insideDefine_ < rhs.insideDefine_;
  116. return name_ < rhs.name_;
  117. }
  118. bool ProcessedClass::operator <(const ProcessedClass& rhs) const
  119. {
  120. if (inherianceDeep_ != rhs.inherianceDeep_)
  121. return inherianceDeep_ < rhs.inherianceDeep_;
  122. if (insideDefine_ != rhs.insideDefine_)
  123. return insideDefine_ < rhs.insideDefine_;
  124. return name_ < rhs.name_;
  125. }
  126. bool MemberRegistrationError::operator <(const MemberRegistrationError& rhs) const
  127. {
  128. if (name_ != rhs.name_)
  129. return name_ < rhs.name_;
  130. return comment_ < rhs.comment_;
  131. }
  132. namespace Result
  133. {
  134. vector<ProcessedEnum> enums_;
  135. // Write result to Generated_Enums.cpp
  136. static void SaveEnums()
  137. {
  138. sort(enums_.begin(), enums_.end());
  139. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Enums.cpp");
  140. ofs <<
  141. "// DO NOT EDIT. This file is generated\n"
  142. "\n"
  143. "// We need register all enums before registration of any functions because functions can use any enums\n"
  144. "\n"
  145. "#include \"../Precompiled.h\"\n"
  146. "#include \"../AngelScript/APITemplates.h\"\n"
  147. "\n"
  148. "#include \"../AngelScript/Generated_Includes.h\"\n"
  149. "\n"
  150. "namespace Urho3D\n"
  151. "{\n"
  152. "\n";
  153. for (const ProcessedEnum& processedEnum : enums_)
  154. {
  155. if (!processedEnum.glue_.size())
  156. continue;
  157. if (!processedEnum.insideDefine_.empty())
  158. ofs << "#ifdef " << processedEnum.insideDefine_ << "\n";
  159. ofs << "// " << processedEnum.comment_ << "\n";
  160. for (const string& glue : processedEnum.glue_)
  161. ofs << glue << "\n";
  162. if (!processedEnum.insideDefine_.empty())
  163. ofs << "#endif\n";
  164. ofs << "\n";
  165. }
  166. ofs <<
  167. "void ASRegisterGeneratedEnums(asIScriptEngine* engine)\n"
  168. "{\n";
  169. bool isFirst = true;
  170. string openedDefine;
  171. for (const ProcessedEnum& processedEnum : enums_)
  172. {
  173. if (processedEnum.insideDefine_ != openedDefine && !openedDefine.empty())
  174. {
  175. ofs << "#endif\n";
  176. openedDefine.clear();
  177. }
  178. if (!isFirst)
  179. ofs << "\n";
  180. if (processedEnum.insideDefine_ != openedDefine && !processedEnum.insideDefine_.empty())
  181. {
  182. ofs << "#ifdef " << processedEnum.insideDefine_ << "\n";
  183. openedDefine = processedEnum.insideDefine_;
  184. }
  185. ofs << " // " << processedEnum.comment_ << "\n";
  186. for (const string& registration : processedEnum.registration_)
  187. ofs << " " << registration << "\n";
  188. isFirst = false;
  189. }
  190. if (!openedDefine.empty())
  191. ofs << "#endif\n";
  192. ofs <<
  193. "}\n"
  194. "\n"
  195. "}\n";
  196. }
  197. // ============================================================================
  198. vector<ProcessedGlobalFunction> globalFunctions_;
  199. // Write result to Generated_GlobalFunctions.cpp
  200. static void SaveGlobalFunctions()
  201. {
  202. sort(globalFunctions_.begin(), globalFunctions_.end());
  203. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_GlobalFunctions.cpp");
  204. ofs <<
  205. "// DO NOT EDIT. This file is generated\n"
  206. "\n"
  207. "#include \"../Precompiled.h\"\n"
  208. "#include \"../AngelScript/APITemplates.h\"\n"
  209. "\n"
  210. "#include \"../AngelScript/Generated_Includes.h\"\n"
  211. "\n"
  212. "namespace Urho3D\n"
  213. "{\n"
  214. "\n";
  215. for (const ProcessedGlobalFunction& globalFunction : globalFunctions_)
  216. {
  217. if (globalFunction.glue_.empty())
  218. continue;
  219. if (!globalFunction.insideDefine_.empty())
  220. ofs << "#ifdef " << globalFunction.insideDefine_ << "\n";
  221. ofs << "// " << globalFunction.comment_ << "\n";
  222. ofs << globalFunction.glue_ << "\n";
  223. if (!globalFunction.insideDefine_.empty())
  224. ofs << "#endif\n";
  225. ofs << "\n";
  226. }
  227. ofs <<
  228. "void ASRegisterGeneratedGlobalFunctions(asIScriptEngine* engine)\n"
  229. "{\n";
  230. bool isFirst = true;
  231. string openedDefine;
  232. string lastComment;
  233. for (const ProcessedGlobalFunction& globalFunction : globalFunctions_)
  234. {
  235. if (globalFunction.insideDefine_ != openedDefine && !openedDefine.empty())
  236. {
  237. ofs << "#endif\n";
  238. openedDefine.clear();
  239. }
  240. if (!isFirst && lastComment != globalFunction.comment_)
  241. ofs << "\n";
  242. if (globalFunction.insideDefine_ != openedDefine && !globalFunction.insideDefine_.empty())
  243. {
  244. ofs << "#ifdef " << globalFunction.insideDefine_ << "\n";
  245. openedDefine = globalFunction.insideDefine_;
  246. }
  247. if (lastComment != globalFunction.comment_)
  248. ofs << " // " << globalFunction.comment_ << "\n";
  249. ofs << " " << globalFunction.registration_ << "\n";
  250. isFirst = false;
  251. lastComment = globalFunction.comment_;
  252. }
  253. if (!openedDefine.empty())
  254. ofs << "#endif\n";
  255. ofs <<
  256. "}\n"
  257. "\n"
  258. "}\n";
  259. }
  260. // ============================================================================
  261. vector<ProcessedGlobalVariable> globalVariables_;
  262. // Write result to Generated_GlobalVariables.cpp
  263. static void SaveGlobalVariables()
  264. {
  265. sort(globalVariables_.begin(), globalVariables_.end());
  266. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_GlobalVariables.cpp");
  267. ofs <<
  268. "// DO NOT EDIT. This file is generated\n"
  269. "\n"
  270. "#include \"../Precompiled.h\"\n"
  271. "#include \"../AngelScript/APITemplates.h\"\n"
  272. "\n"
  273. "#include \"../AngelScript/Generated_Includes.h\"\n"
  274. "\n"
  275. "// Some headers could re-define M_PI, ensure that it's undefined\n"
  276. "#undef M_PI\n"
  277. "\n"
  278. "namespace Urho3D\n"
  279. "{\n"
  280. "\n"
  281. "void ASRegisterGeneratedGlobalVariables(asIScriptEngine* engine)\n"
  282. "{\n";
  283. bool isFirst = true;
  284. string openedDefine;
  285. string lastComment;
  286. for (const ProcessedGlobalVariable& globalVariable : globalVariables_)
  287. {
  288. if (globalVariable.insideDefine_ != openedDefine && !openedDefine.empty())
  289. {
  290. ofs << "#endif\n";
  291. openedDefine.clear();
  292. }
  293. if (!isFirst && lastComment != globalVariable.comment_)
  294. ofs << "\n";
  295. if (globalVariable.insideDefine_ != openedDefine && !globalVariable.insideDefine_.empty())
  296. {
  297. ofs << "#ifdef " << globalVariable.insideDefine_ << "\n";
  298. openedDefine = globalVariable.insideDefine_;
  299. }
  300. if (lastComment != globalVariable.comment_)
  301. ofs << " // " << globalVariable.comment_ << "\n";
  302. ofs << " " << globalVariable.registration_ << "\n";
  303. isFirst = false;
  304. lastComment = globalVariable.comment_;
  305. }
  306. if (!openedDefine.empty())
  307. ofs << "#endif\n";
  308. ofs <<
  309. "}\n"
  310. "\n"
  311. "}\n";
  312. }
  313. // ============================================================================
  314. vector<ProcessedClass> classes_;
  315. // Write result to Generated_ObjectTypes.cpp
  316. static void SaveObjectTypes()
  317. {
  318. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_ObjectTypes.cpp");
  319. ofs <<
  320. "// DO NOT EDIT. This file is generated\n"
  321. "\n"
  322. "// We need register all types before registration of any functions because functions can use any types\n"
  323. "\n"
  324. "#include \"../Precompiled.h\"\n"
  325. "#include \"../AngelScript/APITemplates.h\"\n"
  326. "\n"
  327. "#include \"../AngelScript/Generated_Includes.h\"\n"
  328. "\n"
  329. "namespace Urho3D\n"
  330. "{\n"
  331. "\n"
  332. "void ASRegisterGeneratedObjectTypes(asIScriptEngine* engine)\n"
  333. "{\n";
  334. string openedDefine;
  335. bool isFirst = true;
  336. for (const ProcessedClass& processedClass : classes_)
  337. {
  338. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  339. {
  340. ofs << "#endif\n";
  341. openedDefine.clear();
  342. }
  343. if (!isFirst)
  344. ofs << "\n";
  345. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  346. {
  347. ofs << "#ifdef " << processedClass.insideDefine_ << "\n";
  348. openedDefine = processedClass.insideDefine_;
  349. }
  350. ofs
  351. << " // " << processedClass.comment_ << "\n"
  352. << " " << processedClass.objectTypeRegistration_ << "\n";
  353. isFirst = false;
  354. }
  355. if (!openedDefine.empty())
  356. ofs << "#endif\n";
  357. ofs <<
  358. "}\n"
  359. "\n"
  360. "}\n";
  361. }
  362. // Write result to Generated_DefaultConstructors.cpp
  363. static void SaveDefaultConstructors()
  364. {
  365. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_DefaultConstructors.cpp");
  366. ofs <<
  367. "// DO NOT EDIT. This file is generated\n"
  368. "\n"
  369. "// We need register default constructors before any members to allow using in Array<type>\n"
  370. "\n"
  371. "#include \"../Precompiled.h\"\n"
  372. "#include \"../AngelScript/APITemplates.h\"\n"
  373. "\n"
  374. "#include \"../AngelScript/Generated_Includes.h\"\n"
  375. "\n"
  376. "namespace Urho3D\n"
  377. "{\n";
  378. string openedDefine;
  379. for (const ProcessedClass& processedClass : classes_)
  380. {
  381. if (!processedClass.defaultConstructor_)
  382. continue;
  383. if (processedClass.defaultConstructor_->glue_.empty())
  384. continue;
  385. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  386. {
  387. ofs << "\n#endif\n";
  388. openedDefine.clear();
  389. }
  390. ofs << "\n";
  391. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  392. {
  393. ofs << "#ifdef " << processedClass.insideDefine_ << "\n\n";
  394. openedDefine = processedClass.insideDefine_;
  395. }
  396. ofs <<
  397. "// " << processedClass.defaultConstructor_->comment_ << "\n" <<
  398. processedClass.defaultConstructor_->glue_;
  399. }
  400. if (!openedDefine.empty())
  401. {
  402. ofs << "\n#endif\n";
  403. openedDefine.clear();
  404. }
  405. ofs <<
  406. "\n"
  407. "void ASRegisterGeneratedDefaultConstructors(asIScriptEngine* engine)\n"
  408. "{\n";
  409. bool isFirst = true;
  410. for (const ProcessedClass& processedClass : classes_)
  411. {
  412. if (!processedClass.defaultConstructor_)
  413. continue;
  414. if (processedClass.noBind_)
  415. continue;
  416. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  417. {
  418. ofs << "#endif\n";
  419. openedDefine.clear();
  420. }
  421. if (!isFirst)
  422. ofs << "\n";
  423. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  424. {
  425. ofs << "#ifdef " << processedClass.insideDefine_ << "\n";
  426. openedDefine = processedClass.insideDefine_;
  427. }
  428. ofs <<
  429. " // " << processedClass.defaultConstructor_->comment_ << "\n" <<
  430. " " << processedClass.defaultConstructor_->registration_ << "\n";
  431. isFirst = false;
  432. }
  433. if (!openedDefine.empty())
  434. ofs << "#endif\n";
  435. ofs <<
  436. "}\n"
  437. "\n"
  438. "}\n";
  439. }
  440. // Write result to Generated_Classes.cpp
  441. static void SaveGeneratedClasses()
  442. {
  443. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Classes.cpp");
  444. ofs <<
  445. "// DO NOT EDIT. This file is generated\n"
  446. "\n"
  447. "#include \"../Precompiled.h\"\n"
  448. "#include \"../AngelScript/APITemplates.h\"\n"
  449. "\n"
  450. "#include \"../AngelScript/Generated_Includes.h\"\n"
  451. "#include \"../AngelScript/Generated_Members.h\"\n"
  452. "#include \"../AngelScript/Manual.h\"\n"
  453. "\n"
  454. "namespace Urho3D\n"
  455. "{\n"
  456. "\n"
  457. "void FakeAddRef(void* ptr);\n"
  458. "void FakeReleaseRef(void* ptr);\n";
  459. string openedDefine;
  460. for (ProcessedClass& processedClass : classes_)
  461. {
  462. if (processedClass.noBind_)
  463. continue;
  464. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  465. {
  466. ofs << "\n#endif // def " << openedDefine << "\n";
  467. openedDefine.clear();
  468. }
  469. ofs << "\n";
  470. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  471. {
  472. ofs << "#ifdef " << processedClass.insideDefine_ << "\n\n";
  473. openedDefine = processedClass.insideDefine_;
  474. }
  475. if (processedClass.destructor_ && !processedClass.destructor_->glue_.empty())
  476. {
  477. ofs <<
  478. "// " << processedClass.destructor_->comment_ << "\n"
  479. << processedClass.destructor_->glue_ <<
  480. "\n";
  481. }
  482. for (const SpecialMethodRegistration& nonDefaultConstructor : processedClass.nonDefaultConstructors_)
  483. {
  484. ofs <<
  485. "// " << nonDefaultConstructor.comment_ << "\n"
  486. << nonDefaultConstructor.glue_ <<
  487. "\n";
  488. }
  489. for (const Registration& personalMethod : processedClass.personalMethods_)
  490. {
  491. if (personalMethod.glue_.size())
  492. {
  493. ofs <<
  494. "// " << personalMethod.comment_ << "\n"
  495. << personalMethod.glue_ <<
  496. "\n";
  497. }
  498. }
  499. for (const Registration& personalStaticMethod : processedClass.personalStaticMethods_)
  500. {
  501. if (personalStaticMethod.glue_.size())
  502. {
  503. ofs <<
  504. "// " << personalStaticMethod.comment_ << "\n"
  505. << personalStaticMethod.glue_ <<
  506. "\n";
  507. }
  508. }
  509. ofs <<
  510. "// " << processedClass.comment_ << "\n"
  511. "static void Register_" << processedClass.name_ << "(asIScriptEngine* engine)\n"
  512. "{\n";
  513. bool needGap = false;
  514. sort(processedClass.unregisteredSpecialMethods_.begin(), processedClass.unregisteredSpecialMethods_.end());
  515. for (const MemberRegistrationError& regError : processedClass.unregisteredSpecialMethods_)
  516. {
  517. ofs <<
  518. " // " << regError.comment_ << "\n"
  519. " // " << regError.message_ << "\n";
  520. needGap = true;
  521. }
  522. if (needGap && processedClass.nonDefaultConstructors_.size())
  523. ofs << '\n';
  524. for (const SpecialMethodRegistration& nonDefaultConstructor : processedClass.nonDefaultConstructors_)
  525. {
  526. ofs <<
  527. " // " << nonDefaultConstructor.comment_ << "\n"
  528. " " << nonDefaultConstructor.registration_ << "\n";
  529. needGap = true;
  530. }
  531. if (processedClass.destructor_)
  532. {
  533. if (needGap)
  534. ofs << '\n';
  535. ofs <<
  536. " // " << processedClass.destructor_->comment_ << "\n"
  537. " " << processedClass.destructor_->registration_ << "\n";
  538. needGap = true;
  539. }
  540. if (needGap && processedClass.subclassRegistrations_.size())
  541. ofs << '\n';
  542. for (const string& subclassRegistration : processedClass.subclassRegistrations_)
  543. {
  544. ofs << " " << subclassRegistration << '\n';
  545. needGap = true;
  546. }
  547. if (needGap)
  548. ofs << '\n';
  549. ofs <<
  550. " RegisterMembers_" << processedClass.name_ << "<" << processedClass.name_ << ">(engine, \"" << processedClass.name_ << "\");\n"
  551. "\n"
  552. " #ifdef REGISTER_CLASS_MANUAL_PART_" << processedClass.name_ << "\n"
  553. " REGISTER_CLASS_MANUAL_PART_" << processedClass.name_ << "();\n"
  554. " #endif\n";
  555. for (const MemberRegistrationError& unregisteredPersonalMethod : processedClass.unregisteredPersonalMethods_)
  556. {
  557. ofs <<
  558. "\n"
  559. " // " << unregisteredPersonalMethod.comment_ << "\n"
  560. " // " << unregisteredPersonalMethod.message_ << "\n";
  561. needGap = true;
  562. }
  563. for (const Registration& perosnalMethod : processedClass.personalMethods_)
  564. {
  565. ofs <<
  566. "\n"
  567. " // " << perosnalMethod.comment_ << "\n";
  568. for (const string& reg : perosnalMethod.registration_)
  569. ofs << " " << reg << '\n';
  570. }
  571. for (const MemberRegistrationError& unregisteredPersonalStaticMethod : processedClass.unregisteredPersonalStaticMethods_)
  572. {
  573. ofs <<
  574. "\n"
  575. " // " << unregisteredPersonalStaticMethod.comment_ << "\n"
  576. " // " << unregisteredPersonalStaticMethod.message_ << "\n";
  577. needGap = true;
  578. }
  579. for (const Registration& perosnalStaticMethod : processedClass.personalStaticMethods_)
  580. {
  581. ofs <<
  582. "\n"
  583. " // " << perosnalStaticMethod.comment_ << "\n";
  584. for (const string& reg : perosnalStaticMethod.registration_)
  585. ofs << " " << reg << '\n';
  586. }
  587. if (processedClass.additionalLines_.size())
  588. ofs << '\n';
  589. for (string str : processedClass.additionalLines_)
  590. ofs << str << '\n';
  591. ofs << "}\n";
  592. }
  593. if (!openedDefine.empty())
  594. {
  595. ofs << "\n#endif // def " << openedDefine << "\n";
  596. openedDefine.clear();
  597. }
  598. ofs <<
  599. "\n"
  600. "void ASRegisterGeneratedClasses(asIScriptEngine* engine)\n"
  601. "{\n";
  602. bool isFirst = true;
  603. for (const ProcessedClass& processedClass : classes_)
  604. {
  605. if (processedClass.noBind_)
  606. continue;
  607. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  608. {
  609. ofs << "#endif\n";
  610. openedDefine.clear();
  611. }
  612. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  613. {
  614. if (!isFirst)
  615. ofs << "\n";
  616. ofs << "#ifdef " << processedClass.insideDefine_ << "\n";
  617. openedDefine = processedClass.insideDefine_;
  618. }
  619. ofs << " Register_" << processedClass.name_ << "(engine);\n";
  620. isFirst = false;
  621. }
  622. if (!openedDefine.empty())
  623. ofs << "#endif\n";
  624. ofs <<
  625. "}\n"
  626. "\n"
  627. "}\n";
  628. }
  629. struct MemberCppFile
  630. {
  631. ofstream ofs_;
  632. string openedDefine_;
  633. bool needGap_ = false;
  634. MemberCppFile(const string& dirName)
  635. {
  636. string fileName = _sourceDir + "/Source/Urho3D/AngelScript/Generated_Members_" + dirName + ".cpp";
  637. ofs_ = ofstream(fileName);
  638. ofs_ <<
  639. "// DO NOT EDIT. This file is generated\n"
  640. "\n"
  641. "#include \"../Precompiled.h\"\n"
  642. "#include \"../AngelScript/APITemplates.h\"\n"
  643. "\n"
  644. "#include \"../AngelScript/Generated_Includes.h\"\n"
  645. "#include \"../AngelScript/Generated_ClassMembers.h\"\n"
  646. "#include \"../AngelScript/Manual.h\"\n"
  647. "\n"
  648. "namespace Urho3D\n"
  649. "{\n";
  650. }
  651. };
  652. unordered_map<string, shared_ptr<MemberCppFile>> memberCppFiles_;
  653. shared_ptr<MemberCppFile> GetMemberCppFile(const string& dirName)
  654. {
  655. auto it = memberCppFiles_.find(dirName);
  656. if (it == memberCppFiles_.end())
  657. {
  658. auto newElement = memberCppFiles_.emplace(dirName, make_shared<MemberCppFile>(dirName));
  659. it = newElement.first;
  660. }
  661. return (*it).second;
  662. }
  663. // Write result to GeneratedClassMembers.cpp and GeneratedClassMembers.h // TODO change comment
  664. static void SaveClassMembers()
  665. {
  666. ofstream ofsH = ofstream(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Members.h");
  667. ofsH <<
  668. "// DO NOT EDIT. This file is generated\n"
  669. "\n"
  670. "#pragma once\n"
  671. "\n"
  672. "#include \"../AngelScript/APITemplates.h\"\n"
  673. "\n"
  674. "#include \"../AngelScript/Generated_Includes.h\"\n"
  675. "#include \"../AngelScript/Manual.h\"\n"
  676. "\n"
  677. "namespace Urho3D\n"
  678. "{\n";
  679. string openedDefine;
  680. for (const ProcessedClass& processedClass : classes_)
  681. {
  682. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  683. {
  684. ofsH <<
  685. "\n"
  686. "#endif // def " << openedDefine << "\n";
  687. openedDefine.clear();
  688. }
  689. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  690. {
  691. ofsH <<
  692. "\n"
  693. "#ifdef " << processedClass.insideDefine_ << "\n";
  694. openedDefine = processedClass.insideDefine_;
  695. }
  696. for (const Registration& method : processedClass.templateMethods_)
  697. {
  698. if (method.glue_.size())
  699. {
  700. ofsH <<
  701. "\n"
  702. "// " << method.comment_ << "\n"
  703. << method.glue_;
  704. }
  705. }
  706. for (const Registration& staticMethod : processedClass.templateStaticMethods_)
  707. {
  708. if (staticMethod.glue_.size())
  709. {
  710. ofsH <<
  711. "\n"
  712. "// " << staticMethod.comment_ << "\n"
  713. << staticMethod.glue_;
  714. }
  715. }
  716. ofsH <<
  717. "\n"
  718. "// " << processedClass.comment_ << "\n"
  719. "template <class T> void RegisterMembers_" << processedClass.name_ << "(asIScriptEngine* engine, const char* className)\n"
  720. "{\n";
  721. bool needGap = false;
  722. if (processedClass.baseClassNames_.size())
  723. {
  724. for (const string& baseClassName : processedClass.baseClassNames_)
  725. ofsH << " RegisterMembers_" << baseClassName << "<T>(engine, className);\n";
  726. needGap = true;
  727. }
  728. if (needGap && processedClass.unregisteredTemplateMethods_.size())
  729. ofsH << '\n';
  730. for (const MemberRegistrationError& unregisteredTemplateMethod : processedClass.unregisteredTemplateMethods_)
  731. {
  732. ofsH <<
  733. " // " << unregisteredTemplateMethod.comment_ << "\n"
  734. " // " << unregisteredTemplateMethod.message_ << "\n";
  735. needGap = true;
  736. }
  737. for (const Registration& method : processedClass.templateMethods_)
  738. {
  739. if (needGap)
  740. ofsH << '\n';
  741. ofsH << " // " << method.comment_ << '\n';
  742. for (const string& registration : method.registration_)
  743. ofsH << " " << registration << '\n';
  744. needGap = true;
  745. }
  746. if (needGap && processedClass.unregisteredTemplateStaticMethods_.size())
  747. ofsH << '\n';
  748. for (const MemberRegistrationError& unregisteredTemplateStaticMethod : processedClass.unregisteredTemplateStaticMethods_)
  749. {
  750. ofsH <<
  751. " // " << unregisteredTemplateStaticMethod.comment_ << "\n"
  752. " // " << unregisteredTemplateStaticMethod.message_ << "\n";
  753. needGap = true;
  754. }
  755. for (const Registration& staticMethod : processedClass.templateStaticMethods_)
  756. {
  757. if (needGap)
  758. ofsH << '\n';
  759. ofsH << " // " << staticMethod.comment_ << '\n';
  760. for (const string& registration : staticMethod.registration_)
  761. ofsH << " " << registration << '\n';
  762. needGap = true;
  763. }
  764. if (needGap && processedClass.unregisteredTemplateFields_.size())
  765. ofsH << '\n';
  766. for (const MemberRegistrationError& unregisteredTemplateField : processedClass.unregisteredTemplateFields_)
  767. {
  768. ofsH <<
  769. " // " << unregisteredTemplateField.comment_ << "\n"
  770. " // " << unregisteredTemplateField.message_ << "\n";
  771. needGap = true;
  772. }
  773. for (const Registration& field : processedClass.templateFields_)
  774. {
  775. if (needGap)
  776. ofsH << '\n';
  777. ofsH << " // " << field.comment_ << '\n';
  778. for (const string& registration : field.registration_)
  779. ofsH << " " << registration << '\n';
  780. needGap = true;
  781. }
  782. if (needGap && processedClass.unregisteredTemplateStaticFields_.size())
  783. ofsH << '\n';
  784. for (const MemberRegistrationError& unregisteredTemplateStaticField : processedClass.unregisteredTemplateStaticFields_)
  785. {
  786. ofsH <<
  787. " // " << unregisteredTemplateStaticField.comment_ << "\n"
  788. " // " << unregisteredTemplateStaticField.message_ << "\n";
  789. needGap = true;
  790. }
  791. for (const Registration& field : processedClass.templateStaticFields_)
  792. {
  793. if (needGap)
  794. ofsH << '\n';
  795. ofsH << " // " << field.comment_ << '\n';
  796. for (const string& registration : field.registration_)
  797. ofsH << " " << registration << '\n';
  798. needGap = true;
  799. }
  800. if (needGap)
  801. ofsH << '\n';
  802. ofsH <<
  803. " #ifdef REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "\n"
  804. " REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "();\n"
  805. " #endif\n";
  806. ofsH << "}\n";
  807. }
  808. if (!openedDefine.empty())
  809. {
  810. ofsH <<
  811. "\n"
  812. "#endif // def " << openedDefine << "\n";
  813. openedDefine.clear();
  814. }
  815. ofsH <<
  816. "\n"
  817. "} // namespace Urho3D\n";
  818. }
  819. static void SaveClasses()
  820. {
  821. sort(classes_.begin(), classes_.end());
  822. SaveObjectTypes();
  823. SaveDefaultConstructors();
  824. SaveGeneratedClasses();
  825. SaveClassMembers();
  826. }
  827. // ============================================================================
  828. // List of all required header files
  829. static vector<string> headers_;
  830. // Discarded header files for statistic
  831. static vector<string> ignoredHeaders_;
  832. // Add header to lists if not added yet
  833. void AddHeader(const string& headerFile)
  834. {
  835. if (IsIgnoredHeader(headerFile))
  836. {
  837. if (!CONTAINS(ignoredHeaders_, headerFile))
  838. ignoredHeaders_.push_back(headerFile);
  839. }
  840. else
  841. {
  842. if (!CONTAINS(headers_, headerFile))
  843. headers_.push_back(headerFile);
  844. }
  845. }
  846. // Write result to Generated_Includes.h
  847. static void SaveIncludes()
  848. {
  849. sort(headers_.begin(), headers_.end());
  850. sort(ignoredHeaders_.begin(), ignoredHeaders_.end());
  851. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Includes.h");
  852. ofs <<
  853. "// DO NOT EDIT. This file is generated\n"
  854. "\n"
  855. "#pragma once\n"
  856. "\n";
  857. string openedDefine;
  858. bool isFirst = true;
  859. for (const string& header : headers_)
  860. {
  861. string insideDefine = InsideDefine(header);
  862. if (insideDefine != openedDefine)
  863. {
  864. if (!openedDefine.empty())
  865. {
  866. ofs << "#endif\n";
  867. openedDefine.clear();
  868. }
  869. if (!isFirst) // First include can be guarded. Avoid print \n before it
  870. ofs << "\n";
  871. if (!insideDefine.empty())
  872. {
  873. ofs << "#ifdef " << insideDefine << "\n";
  874. openedDefine = insideDefine;
  875. }
  876. }
  877. ofs << "#include \"" << header << "\"\n";
  878. isFirst = false;
  879. }
  880. if (!openedDefine.empty())
  881. {
  882. ofs << "#endif\n";
  883. openedDefine.clear();
  884. }
  885. if (headers_.size() > 0)
  886. ofs << "\n";
  887. if (ignoredHeaders_.size() > 0)
  888. ofs << "// Ignored headers\n\n";
  889. isFirst = true;
  890. for (const string& header : ignoredHeaders_)
  891. {
  892. string insideDefine = InsideDefine(header);
  893. if (insideDefine != openedDefine)
  894. {
  895. if (!openedDefine.empty())
  896. {
  897. ofs << "//#endif\n";
  898. openedDefine.clear();
  899. }
  900. if (!isFirst) // First include can be guarded. Avoid print \n before it
  901. ofs << "\n";
  902. if (!insideDefine.empty())
  903. {
  904. ofs << "//#ifdef " << insideDefine << "\n";
  905. openedDefine = insideDefine;
  906. }
  907. }
  908. ofs << "//#include \"" << header << "\"\n";
  909. isFirst = false;
  910. }
  911. if (!openedDefine.empty())
  912. ofs << "//#endif\n";
  913. }
  914. }
  915. void SaveResult()
  916. {
  917. Result::SaveEnums();
  918. Result::SaveGlobalFunctions();
  919. Result::SaveGlobalVariables();
  920. Result::SaveClasses();
  921. Result::SaveIncludes();
  922. }
  923. }