ASResult.cpp 35 KB

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