ASResult.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  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 "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.fakeRefBehaviors_.size())
  541. ofs << '\n';
  542. for (const SpecialMethodRegistration& fakeRefBehavior : processedClass.fakeRefBehaviors_)
  543. {
  544. if (fakeRefBehavior.comment_.size())
  545. ofs << " // " << fakeRefBehavior.comment_ << '\n';
  546. ofs << " " + fakeRefBehavior.registration_ << '\n';
  547. needGap = true;
  548. }
  549. if (needGap && processedClass.subclassRegistrations_.size())
  550. ofs << '\n';
  551. for (const string& subclassRegistration : processedClass.subclassRegistrations_)
  552. {
  553. ofs << " " << subclassRegistration << '\n';
  554. needGap = true;
  555. }
  556. if (needGap)
  557. ofs << '\n';
  558. ofs <<
  559. " RegisterMembers_" << processedClass.name_ << "<" << processedClass.name_ << ">(engine, \"" << processedClass.name_ << "\");\n"
  560. "\n"
  561. " #ifdef REGISTER_CLASS_MANUAL_PART_" << processedClass.name_ << "\n"
  562. " REGISTER_CLASS_MANUAL_PART_" << processedClass.name_ << "();\n"
  563. " #endif\n";
  564. for (const MemberRegistrationError& unregisteredPersonalMethod : processedClass.unregisteredPersonalMethods_)
  565. {
  566. ofs <<
  567. "\n"
  568. " // " << unregisteredPersonalMethod.comment_ << "\n"
  569. " // " << unregisteredPersonalMethod.message_ << "\n";
  570. needGap = true;
  571. }
  572. for (const Registration& perosnalMethod : processedClass.personalMethods_)
  573. {
  574. ofs <<
  575. "\n"
  576. " // " << perosnalMethod.comment_ << "\n";
  577. for (const string& reg : perosnalMethod.registration_)
  578. ofs << " " << reg << '\n';
  579. }
  580. for (const MemberRegistrationError& unregisteredPersonalStaticMethod : processedClass.unregisteredPersonalStaticMethods_)
  581. {
  582. ofs <<
  583. "\n"
  584. " // " << unregisteredPersonalStaticMethod.comment_ << "\n"
  585. " // " << unregisteredPersonalStaticMethod.message_ << "\n";
  586. needGap = true;
  587. }
  588. for (const Registration& perosnalStaticMethod : processedClass.personalStaticMethods_)
  589. {
  590. ofs <<
  591. "\n"
  592. " // " << perosnalStaticMethod.comment_ << "\n";
  593. for (const string& reg : perosnalStaticMethod.registration_)
  594. ofs << " " << reg << '\n';
  595. }
  596. if (processedClass.additionalLines_.size())
  597. ofs << '\n';
  598. for (string str : processedClass.additionalLines_)
  599. ofs << str << '\n';
  600. ofs << "}\n";
  601. }
  602. if (!openedDefine.empty())
  603. {
  604. ofs << "\n#endif // def " << openedDefine << "\n";
  605. openedDefine.clear();
  606. }
  607. ofs <<
  608. "\n"
  609. "void ASRegisterGeneratedClasses(asIScriptEngine* engine)\n"
  610. "{\n";
  611. bool isFirst = true;
  612. for (const ProcessedClass& processedClass : classes_)
  613. {
  614. if (processedClass.noBind_)
  615. continue;
  616. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  617. {
  618. ofs << "#endif\n";
  619. openedDefine.clear();
  620. }
  621. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  622. {
  623. if (!isFirst)
  624. ofs << "\n";
  625. ofs << "#ifdef " << processedClass.insideDefine_ << "\n";
  626. openedDefine = processedClass.insideDefine_;
  627. }
  628. ofs << " Register_" << processedClass.name_ << "(engine);\n";
  629. isFirst = false;
  630. }
  631. if (!openedDefine.empty())
  632. ofs << "#endif\n";
  633. ofs <<
  634. "}\n"
  635. "\n"
  636. "}\n";
  637. }
  638. struct MemberCppFile
  639. {
  640. ofstream ofs_;
  641. string openedDefine_;
  642. bool needGap_ = false;
  643. MemberCppFile(const string& dirName)
  644. {
  645. string fileName = _sourceDir + "/Source/Urho3D/AngelScript/Generated_Members_" + dirName + ".cpp";
  646. ofs_ = ofstream(fileName);
  647. ofs_ <<
  648. "// DO NOT EDIT. This file is generated\n"
  649. "\n"
  650. "#include \"../Precompiled.h\"\n"
  651. "#include \"../AngelScript/APITemplates.h\"\n"
  652. "\n"
  653. "#include \"../AngelScript/Generated_Includes.h\"\n"
  654. "#include \"../AngelScript/Generated_ClassMembers.h\"\n"
  655. "#include \"../AngelScript/Manual.h\"\n"
  656. "\n"
  657. "namespace Urho3D\n"
  658. "{\n";
  659. }
  660. };
  661. unordered_map<string, shared_ptr<MemberCppFile>> memberCppFiles_;
  662. shared_ptr<MemberCppFile> GetMemberCppFile(const string& dirName)
  663. {
  664. auto it = memberCppFiles_.find(dirName);
  665. if (it == memberCppFiles_.end())
  666. {
  667. auto newElement = memberCppFiles_.emplace(dirName, make_shared<MemberCppFile>(dirName));
  668. it = newElement.first;
  669. }
  670. return (*it).second;
  671. }
  672. // Write result to GeneratedClassMembers.cpp and GeneratedClassMembers.h // TODO change comment
  673. static void SaveClassMembers()
  674. {
  675. ofstream ofsH = ofstream(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Members.h");
  676. ofsH <<
  677. "// DO NOT EDIT. This file is generated\n"
  678. "\n"
  679. "#pragma once\n"
  680. "\n"
  681. "#include \"../AngelScript/APITemplates.h\"\n"
  682. "\n"
  683. "#include \"../AngelScript/Generated_Includes.h\"\n"
  684. "#include \"../AngelScript/Manual.h\"\n"
  685. "\n"
  686. "namespace Urho3D\n"
  687. "{\n";
  688. string openedDefine;
  689. for (const ProcessedClass& processedClass : classes_)
  690. {
  691. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  692. {
  693. ofsH <<
  694. "\n"
  695. "#endif // def " << openedDefine << "\n";
  696. openedDefine.clear();
  697. }
  698. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  699. {
  700. ofsH <<
  701. "\n"
  702. "#ifdef " << processedClass.insideDefine_ << "\n";
  703. openedDefine = processedClass.insideDefine_;
  704. }
  705. for (const Registration& method : processedClass.templateMethods_)
  706. {
  707. if (method.glue_.size())
  708. {
  709. ofsH <<
  710. "\n"
  711. "// " << method.comment_ << "\n"
  712. << method.glue_;
  713. }
  714. }
  715. for (const Registration& staticMethod : processedClass.templateStaticMethods_)
  716. {
  717. if (staticMethod.glue_.size())
  718. {
  719. ofsH <<
  720. "\n"
  721. "// " << staticMethod.comment_ << "\n"
  722. << staticMethod.glue_;
  723. }
  724. }
  725. ofsH <<
  726. "\n"
  727. "// " << processedClass.comment_ << "\n"
  728. "template <class T> void RegisterMembers_" << processedClass.name_ << "(asIScriptEngine* engine, const char* className)\n"
  729. "{\n";
  730. bool needGap = false;
  731. if (processedClass.baseClassNames_.size())
  732. {
  733. for (const string& baseClassName : processedClass.baseClassNames_)
  734. ofsH << " RegisterMembers_" << baseClassName << "<T>(engine, className);\n";
  735. needGap = true;
  736. }
  737. if (needGap && processedClass.unregisteredTemplateMethods_.size())
  738. ofsH << '\n';
  739. for (const MemberRegistrationError& unregisteredTemplateMethod : processedClass.unregisteredTemplateMethods_)
  740. {
  741. ofsH <<
  742. " // " << unregisteredTemplateMethod.comment_ << "\n"
  743. " // " << unregisteredTemplateMethod.message_ << "\n";
  744. needGap = true;
  745. }
  746. for (const Registration& method : processedClass.templateMethods_)
  747. {
  748. if (needGap)
  749. ofsH << '\n';
  750. ofsH << " // " << method.comment_ << '\n';
  751. for (const string& registration : method.registration_)
  752. ofsH << " " << registration << '\n';
  753. needGap = true;
  754. }
  755. if (needGap && processedClass.unregisteredTemplateStaticMethods_.size())
  756. ofsH << '\n';
  757. for (const MemberRegistrationError& unregisteredTemplateStaticMethod : processedClass.unregisteredTemplateStaticMethods_)
  758. {
  759. ofsH <<
  760. " // " << unregisteredTemplateStaticMethod.comment_ << "\n"
  761. " // " << unregisteredTemplateStaticMethod.message_ << "\n";
  762. needGap = true;
  763. }
  764. for (const Registration& staticMethod : processedClass.templateStaticMethods_)
  765. {
  766. if (needGap)
  767. ofsH << '\n';
  768. ofsH << " // " << staticMethod.comment_ << '\n';
  769. for (const string& registration : staticMethod.registration_)
  770. ofsH << " " << registration << '\n';
  771. needGap = true;
  772. }
  773. if (needGap && processedClass.unregisteredTemplateFields_.size())
  774. ofsH << '\n';
  775. for (const MemberRegistrationError& unregisteredTemplateField : processedClass.unregisteredTemplateFields_)
  776. {
  777. ofsH <<
  778. " // " << unregisteredTemplateField.comment_ << "\n"
  779. " // " << unregisteredTemplateField.message_ << "\n";
  780. needGap = true;
  781. }
  782. for (const Registration& field : processedClass.templateFields_)
  783. {
  784. if (needGap)
  785. ofsH << '\n';
  786. ofsH << " // " << field.comment_ << '\n';
  787. for (const string& registration : field.registration_)
  788. ofsH << " " << registration << '\n';
  789. needGap = true;
  790. }
  791. if (needGap && processedClass.unregisteredTemplateStaticFields_.size())
  792. ofsH << '\n';
  793. for (const MemberRegistrationError& unregisteredTemplateStaticField : processedClass.unregisteredTemplateStaticFields_)
  794. {
  795. ofsH <<
  796. " // " << unregisteredTemplateStaticField.comment_ << "\n"
  797. " // " << unregisteredTemplateStaticField.message_ << "\n";
  798. needGap = true;
  799. }
  800. for (const Registration& field : processedClass.templateStaticFields_)
  801. {
  802. if (needGap)
  803. ofsH << '\n';
  804. ofsH << " // " << field.comment_ << '\n';
  805. for (const string& registration : field.registration_)
  806. ofsH << " " << registration << '\n';
  807. needGap = true;
  808. }
  809. if (needGap)
  810. ofsH << '\n';
  811. ofsH <<
  812. " #ifdef REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "\n"
  813. " REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "();\n"
  814. " #endif\n";
  815. ofsH << "}\n";
  816. }
  817. if (!openedDefine.empty())
  818. {
  819. ofsH <<
  820. "\n"
  821. "#endif // def " << openedDefine << "\n";
  822. openedDefine.clear();
  823. }
  824. ofsH <<
  825. "\n"
  826. "} // namespace Urho3D\n";
  827. }
  828. static void SaveClasses()
  829. {
  830. sort(classes_.begin(), classes_.end());
  831. SaveObjectTypes();
  832. SaveDefaultConstructors();
  833. SaveGeneratedClasses();
  834. SaveClassMembers();
  835. }
  836. // ============================================================================
  837. // List of all required header files
  838. static vector<string> headers_;
  839. // Discarded header files for statistic
  840. static vector<string> ignoredHeaders_;
  841. // Add header to lists if not added yet
  842. void AddHeader(const string& headerFile)
  843. {
  844. if (IsIgnoredHeader(headerFile))
  845. {
  846. if (!CONTAINS(ignoredHeaders_, headerFile))
  847. ignoredHeaders_.push_back(headerFile);
  848. }
  849. else
  850. {
  851. if (!CONTAINS(headers_, headerFile))
  852. headers_.push_back(headerFile);
  853. }
  854. }
  855. // Write result to Generated_Includes.h
  856. static void SaveIncludes()
  857. {
  858. sort(headers_.begin(), headers_.end());
  859. sort(ignoredHeaders_.begin(), ignoredHeaders_.end());
  860. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Includes.h");
  861. ofs <<
  862. "// DO NOT EDIT. This file is generated\n"
  863. "\n"
  864. "#pragma once\n"
  865. "\n";
  866. string openedDefine;
  867. bool isFirst = true;
  868. for (const string& header : headers_)
  869. {
  870. string insideDefine = InsideDefine(header);
  871. if (insideDefine != openedDefine)
  872. {
  873. if (!openedDefine.empty())
  874. {
  875. ofs << "#endif\n";
  876. openedDefine.clear();
  877. }
  878. if (!isFirst) // First include can be guarded. Avoid print \n before it
  879. ofs << "\n";
  880. if (!insideDefine.empty())
  881. {
  882. ofs << "#ifdef " << insideDefine << "\n";
  883. openedDefine = insideDefine;
  884. }
  885. }
  886. ofs << "#include \"" << header << "\"\n";
  887. isFirst = false;
  888. }
  889. if (!openedDefine.empty())
  890. {
  891. ofs << "#endif\n";
  892. openedDefine.clear();
  893. }
  894. if (headers_.size() > 0)
  895. ofs << "\n";
  896. if (ignoredHeaders_.size() > 0)
  897. ofs << "// Ignored headers\n\n";
  898. isFirst = true;
  899. for (const string& header : ignoredHeaders_)
  900. {
  901. string insideDefine = InsideDefine(header);
  902. if (insideDefine != openedDefine)
  903. {
  904. if (!openedDefine.empty())
  905. {
  906. ofs << "//#endif\n";
  907. openedDefine.clear();
  908. }
  909. if (!isFirst) // First include can be guarded. Avoid print \n before it
  910. ofs << "\n";
  911. if (!insideDefine.empty())
  912. {
  913. ofs << "//#ifdef " << insideDefine << "\n";
  914. openedDefine = insideDefine;
  915. }
  916. }
  917. ofs << "//#include \"" << header << "\"\n";
  918. isFirst = false;
  919. }
  920. if (!openedDefine.empty())
  921. ofs << "//#endif\n";
  922. }
  923. }
  924. void SaveResult()
  925. {
  926. Result::SaveEnums();
  927. Result::SaveGlobalFunctions();
  928. Result::SaveGlobalVariables();
  929. Result::SaveClasses();
  930. Result::SaveIncludes();
  931. }
  932. }