ASResult.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  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/GeneratedIncludes.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/GeneratedIncludes.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 GeneratedEnums.cpp
  136. static void SaveEnums()
  137. {
  138. sort(enums_.begin(), enums_.end());
  139. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/GeneratedEnums.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/GeneratedIncludes.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 GlobalFunctions.cpp
  200. static void SaveGlobalFunctions()
  201. {
  202. sort(globalFunctions_.begin(), globalFunctions_.end());
  203. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/GeneratedGlobalFunctions.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/GeneratedIncludes.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 GlobalVariables.cpp
  263. static void SaveGlobalVariables()
  264. {
  265. sort(globalVariables_.begin(), globalVariables_.end());
  266. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/GeneratedGlobalVariables.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/GeneratedIncludes.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 GeneratedObjectTypes.cpp
  316. static void SaveObjectTypes()
  317. {
  318. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/GeneratedObjectTypes.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/GeneratedIncludes.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 GeneratedDefaultConstructors.cpp
  363. static void SaveDefaultConstructors()
  364. {
  365. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/GeneratedDefaultConstructors.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/GeneratedIncludes.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 GeneratedClasses.cpp
  441. static void SaveGeneratedClasses()
  442. {
  443. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/GeneratedClasses.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/GeneratedIncludes.h\"\n"
  451. "#include \"../AngelScript/GeneratedClassMembers.h\"\n"
  452. "#include \"../AngelScript/Generated_Members.h\"\n"
  453. "#include \"../AngelScript/Manual.h\"\n"
  454. "\n"
  455. "namespace Urho3D\n"
  456. "{\n"
  457. "\n"
  458. "void FakeAddRef(void* ptr);\n"
  459. "void FakeReleaseRef(void* ptr);\n";
  460. string openedDefine;
  461. for (ProcessedClass& processedClass : classes_)
  462. {
  463. if (processedClass.noBind_)
  464. continue;
  465. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  466. {
  467. ofs << "\n#endif // def " << openedDefine << "\n";
  468. openedDefine.clear();
  469. }
  470. ofs << "\n";
  471. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  472. {
  473. ofs << "#ifdef " << processedClass.insideDefine_ << "\n\n";
  474. openedDefine = processedClass.insideDefine_;
  475. }
  476. if (processedClass.destructor_ && !processedClass.destructor_->glue_.empty())
  477. {
  478. ofs <<
  479. "// " << processedClass.destructor_->comment_ << "\n"
  480. << processedClass.destructor_->glue_ <<
  481. "\n";
  482. }
  483. for (const SpecialMethodRegistration& nonDefaultConstructor : processedClass.nonDefaultConstructors_)
  484. {
  485. ofs <<
  486. "// " << nonDefaultConstructor.comment_ << "\n"
  487. << nonDefaultConstructor.glue_ <<
  488. "\n";
  489. }
  490. for (const Registration& personalMethod : processedClass.personalMethods_)
  491. {
  492. if (personalMethod.glue_.size())
  493. {
  494. ofs <<
  495. "// " << personalMethod.comment_ << "\n"
  496. << personalMethod.glue_ <<
  497. "\n";
  498. }
  499. }
  500. for (const Registration& personalStaticMethod : processedClass.personalStaticMethods_)
  501. {
  502. if (personalStaticMethod.glue_.size())
  503. {
  504. ofs <<
  505. "// " << personalStaticMethod.comment_ << "\n"
  506. << personalStaticMethod.glue_ <<
  507. "\n";
  508. }
  509. }
  510. ofs <<
  511. "// " << processedClass.comment_ << "\n"
  512. "static void Register_" << processedClass.name_ << "(asIScriptEngine* engine)\n"
  513. "{\n";
  514. bool needGap = false;
  515. sort(processedClass.unregisteredSpecialMethods_.begin(), processedClass.unregisteredSpecialMethods_.end());
  516. for (const MemberRegistrationError& regError : processedClass.unregisteredSpecialMethods_)
  517. {
  518. ofs <<
  519. " // " << regError.comment_ << "\n"
  520. " // " << regError.message_ << "\n";
  521. needGap = true;
  522. }
  523. if (needGap && processedClass.nonDefaultConstructors_.size())
  524. ofs << '\n';
  525. for (const SpecialMethodRegistration& nonDefaultConstructor : processedClass.nonDefaultConstructors_)
  526. {
  527. ofs <<
  528. " // " << nonDefaultConstructor.comment_ << "\n"
  529. " " << nonDefaultConstructor.registration_ << "\n";
  530. needGap = true;
  531. }
  532. if (processedClass.destructor_)
  533. {
  534. if (needGap)
  535. ofs << '\n';
  536. ofs <<
  537. " // " << processedClass.destructor_->comment_ << "\n"
  538. " " << processedClass.destructor_->registration_ << "\n";
  539. needGap = true;
  540. }
  541. if (needGap && processedClass.fakeRefBehaviors_.size())
  542. ofs << '\n';
  543. for (const SpecialMethodRegistration& fakeRefBehavior : processedClass.fakeRefBehaviors_)
  544. {
  545. if (fakeRefBehavior.comment_.size())
  546. ofs << " // " << fakeRefBehavior.comment_ << '\n';
  547. ofs << " " + fakeRefBehavior.registration_ << '\n';
  548. needGap = true;
  549. }
  550. if (needGap && processedClass.subclassRegistrations_.size())
  551. ofs << '\n';
  552. for (const string& subclassRegistration : processedClass.subclassRegistrations_)
  553. {
  554. ofs << " " << subclassRegistration << '\n';
  555. needGap = true;
  556. }
  557. if (needGap)
  558. ofs << '\n';
  559. ofs <<
  560. " MemberCollection members;\n"
  561. " RegisterMembers_" << processedClass.name_ << "<" << processedClass.name_ << ">(engine, \"" << processedClass.name_ << "\");\n"
  562. " CollectMembers_" << processedClass.name_ << "(members);\n"
  563. " RegisterMembers(engine, \"" << processedClass.name_ << "\", members);\n"
  564. "\n"
  565. " #ifdef REGISTER_CLASS_MANUAL_PART_" << processedClass.name_ << "\n"
  566. " REGISTER_CLASS_MANUAL_PART_" << processedClass.name_ << "();\n"
  567. " #endif\n";
  568. for (const Registration& perosnalMethod : processedClass.personalMethods_)
  569. {
  570. ofs <<
  571. "\n"
  572. " // " << perosnalMethod.comment_ << "\n";
  573. for (const string& reg : perosnalMethod.registration_)
  574. ofs << " " << reg << '\n';
  575. }
  576. for (const Registration& perosnalStaticMethod : processedClass.personalStaticMethods_)
  577. {
  578. ofs <<
  579. "\n"
  580. " // " << perosnalStaticMethod.comment_ << "\n";
  581. for (const string& reg : perosnalStaticMethod.registration_)
  582. ofs << " " << reg << '\n';
  583. }
  584. if (processedClass.additionalLines_.size())
  585. ofs << '\n';
  586. for (string str : processedClass.additionalLines_)
  587. ofs << str << '\n';
  588. ofs << "}\n";
  589. }
  590. if (!openedDefine.empty())
  591. {
  592. ofs << "\n#endif // def " << openedDefine << "\n";
  593. openedDefine.clear();
  594. }
  595. ofs <<
  596. "\n"
  597. "void ASRegisterGeneratedClasses(asIScriptEngine* engine)\n"
  598. "{\n";
  599. bool isFirst = true;
  600. for (const ProcessedClass& processedClass : classes_)
  601. {
  602. if (processedClass.noBind_)
  603. continue;
  604. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  605. {
  606. ofs << "#endif\n";
  607. openedDefine.clear();
  608. }
  609. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  610. {
  611. if (!isFirst)
  612. ofs << "\n";
  613. ofs << "#ifdef " << processedClass.insideDefine_ << "\n";
  614. openedDefine = processedClass.insideDefine_;
  615. }
  616. ofs << " Register_" << processedClass.name_ << "(engine);\n";
  617. isFirst = false;
  618. }
  619. if (!openedDefine.empty())
  620. ofs << "#endif\n";
  621. ofs <<
  622. "}\n"
  623. "\n"
  624. "}\n";
  625. }
  626. struct MemberCppFile
  627. {
  628. ofstream ofs_;
  629. string openedDefine_;
  630. bool needGap_ = false;
  631. MemberCppFile(const string& dirName)
  632. {
  633. string fileName = _sourceDir + "/Source/Urho3D/AngelScript/Generated_Members_" + dirName + ".cpp";
  634. ofs_ = ofstream(fileName);
  635. ofs_ <<
  636. "// DO NOT EDIT. This file is generated\n"
  637. "\n"
  638. "#include \"../Precompiled.h\"\n"
  639. "#include \"../AngelScript/APITemplates.h\"\n"
  640. "\n"
  641. "#include \"../AngelScript/GeneratedIncludes.h\"\n"
  642. "#include \"../AngelScript/GeneratedClassMembers.h\"\n"
  643. "#include \"../AngelScript/Manual.h\"\n"
  644. "\n"
  645. "namespace Urho3D\n"
  646. "{\n";
  647. }
  648. };
  649. unordered_map<string, shared_ptr<MemberCppFile>> memberCppFiles_;
  650. shared_ptr<MemberCppFile> GetMemberCppFile(const string& dirName)
  651. {
  652. auto it = memberCppFiles_.find(dirName);
  653. if (it == memberCppFiles_.end())
  654. {
  655. auto newElement = memberCppFiles_.emplace(dirName, make_shared<MemberCppFile>(dirName));
  656. it = newElement.first;
  657. }
  658. return (*it).second;
  659. }
  660. // Write result to GeneratedClassMembers.cpp and GeneratedClassMembers.h // TODO change comment
  661. static void SaveClassMembers()
  662. {
  663. for (ProcessedClass& processedClass : classes_)
  664. {
  665. shared_ptr<MemberCppFile> file = GetMemberCppFile(processedClass.dirName_);
  666. if (processedClass.insideDefine_ != file->openedDefine_ && !file->openedDefine_.empty())
  667. {
  668. file->ofs_ <<
  669. "\n"
  670. "#endif // def " << file->openedDefine_ << "\n";
  671. file->openedDefine_.clear();
  672. }
  673. if (processedClass.insideDefine_ != file->openedDefine_ && !processedClass.insideDefine_.empty())
  674. {
  675. file->ofs_ <<
  676. "\n"
  677. "#ifdef " << processedClass.insideDefine_ << "\n";
  678. file->openedDefine_ = processedClass.insideDefine_;
  679. }
  680. for (const MethodRegistration& method : processedClass.methods_)
  681. {
  682. if (!method.glue_.empty())
  683. {
  684. file->ofs_ <<
  685. "\n"
  686. "// " << method.cppDeclaration_ << "\n"
  687. << method.glue_;
  688. }
  689. }
  690. for (const StaticMethodRegistration& staticMethod : processedClass.staticMethods_)
  691. {
  692. if (!staticMethod.glue_.empty())
  693. {
  694. file->ofs_ <<
  695. "\n"
  696. "// " << staticMethod.cppDeclaration_ << "\n"
  697. << staticMethod.glue_;
  698. }
  699. }
  700. file->ofs_ <<
  701. "\n"
  702. "// " << processedClass.comment_ << "\n"
  703. "void CollectMembers_" << processedClass.name_ << "(MemberCollection& members)\n"
  704. "{\n";
  705. file->needGap_ = false;
  706. if (processedClass.baseClassNames_.size())
  707. {
  708. for (const string& baseClassName : processedClass.baseClassNames_)
  709. file->ofs_ << " CollectMembers_" << baseClassName << "(members);\n";
  710. file->needGap_ = true;
  711. }
  712. if (file->needGap_ && processedClass.hiddenMethods_.size())
  713. file->ofs_ << '\n';
  714. for (const string& hiddenMethod : processedClass.hiddenMethods_)
  715. {
  716. string escaped = ReplaceAll(hiddenMethod, "\"", "\\\"");
  717. file->ofs_ << " Remove(members.methods_, \"" << escaped << "\");\n";
  718. file->needGap_ = true;
  719. }
  720. if (file->needGap_ && processedClass.hiddenStaticMethods_.size())
  721. file->ofs_ << '\n';
  722. for (const string& hiddenStaticMethod : processedClass.hiddenStaticMethods_)
  723. {
  724. string escaped = ReplaceAll(hiddenStaticMethod, "\"", "\\\"");
  725. file->ofs_ << " Remove(members.staticMethods_, \"" << escaped << "\");\n";
  726. file->needGap_ = true;
  727. }
  728. if (file->needGap_ && processedClass.hiddenFields_.size())
  729. file->ofs_ << '\n';
  730. for (const string& hiddenField : processedClass.hiddenFields_)
  731. {
  732. string escaped = ReplaceAll(hiddenField, "\"", "\\\"");
  733. file->ofs_ << " Remove(members.fields_, \"" << escaped << "\");\n";
  734. file->ofs_ << " Remove(members.wrappedFields_, \"" << escaped << "\");\n";
  735. file->needGap_ = true;
  736. }
  737. if (file->needGap_ && processedClass.hiddenStaticFields_.size())
  738. file->ofs_ << '\n';
  739. for (const string& hiddenStaticField : processedClass.hiddenStaticFields_)
  740. {
  741. string escaped = ReplaceAll(hiddenStaticField, "\"", "\\\"");
  742. file->ofs_ << " Remove(members.staticFields_, \"" << escaped << "\");\n";
  743. file->needGap_ = true;
  744. }
  745. sort(processedClass.unregisteredMethods_.begin(), processedClass.unregisteredMethods_.end());
  746. if (file->needGap_ && processedClass.unregisteredMethods_.size())
  747. file->ofs_ << '\n';
  748. for (const MemberRegistrationError& unregisteredMethod : processedClass.unregisteredMethods_)
  749. {
  750. file->ofs_ <<
  751. " // " << unregisteredMethod.comment_ << "\n"
  752. " // " << unregisteredMethod.message_ << "\n";
  753. file->needGap_ = true;
  754. }
  755. if (file->needGap_ && processedClass.methods_.size())
  756. file->ofs_ << '\n';
  757. // TODO сортировать
  758. for (const MethodRegistration& method : processedClass.methods_)
  759. {
  760. const RegisterObjectMethodArgs& args = method.registration_;
  761. assert(args.asDeclarations_.size());
  762. for (const string& asDeclaration : args.asDeclarations_)
  763. file->ofs_ << " members.methods_.Push(RegisterObjectMethodArgs(\"" << method.cppDeclaration_ << "\", \"" << asDeclaration << "\", " << args.funcPointer_ << ", " << args.callConv_ << "));\n";
  764. file->needGap_ = true;
  765. }
  766. if (file->needGap_ && processedClass.unregisteredStaticMethods_.size())
  767. file->ofs_ << '\n';
  768. for (const MemberRegistrationError& unregisteredStaticMethod : processedClass.unregisteredStaticMethods_)
  769. {
  770. file->ofs_ <<
  771. " // " << unregisteredStaticMethod.comment_ << "\n"
  772. " // " << unregisteredStaticMethod.message_ << "\n";
  773. file->needGap_ = true;
  774. }
  775. if (file->needGap_ && processedClass.staticMethods_.size())
  776. file->ofs_ << '\n';
  777. for (const StaticMethodRegistration& staticMethod : processedClass.staticMethods_)
  778. {
  779. const RegisterGlobalFunctionArgs& args = staticMethod.registration_;
  780. assert(args.asDeclarations_.size());
  781. for (const string& asDeclaration : args.asDeclarations_)
  782. file->ofs_ << " members.staticMethods_.Push(RegisterGlobalFunctionArgs(\"" << staticMethod.cppDeclaration_ << "\", \"" << asDeclaration << "\", " << args.funcPointer_ << ", " << args.callConv_ << "));\n";
  783. file->needGap_ = true;
  784. }
  785. if (file->needGap_ && processedClass.unregisteredFields_.size())
  786. file->ofs_ << '\n';
  787. for (const MemberRegistrationError& unregisteredField : processedClass.unregisteredFields_)
  788. {
  789. file->ofs_ <<
  790. " // " << unregisteredField.comment_ << "\n"
  791. " // " << unregisteredField.message_ << "\n";
  792. file->needGap_ = true;
  793. }
  794. if (file->needGap_ && processedClass.fields_.size())
  795. file->ofs_ << '\n';
  796. for (const FieldRegistration& field : processedClass.fields_)
  797. {
  798. const RegisterObjectPropertyArgs& args = field.registration_;
  799. assert(args.asDeclarations_.size());
  800. for (const string& asDeclaration : args.asDeclarations_)
  801. file->ofs_ << " members.fields_.Push(RegisterObjectPropertyArgs(\"" << field.cppDeclaration_ << "\", \"" << asDeclaration << "\", " << args.byteOffset_ << "));\n";
  802. file->needGap_ = true;
  803. }
  804. if (file->needGap_ && processedClass.unregisteredStaticFields_.size())
  805. file->ofs_ << '\n';
  806. for (const MemberRegistrationError& unregisteredStaticField : processedClass.unregisteredStaticFields_)
  807. {
  808. file->ofs_ <<
  809. " // " << unregisteredStaticField.comment_ << "\n"
  810. " // " << unregisteredStaticField.message_ << "\n";
  811. file->needGap_ = true;
  812. }
  813. if (file->needGap_ && processedClass.staticFields_.size())
  814. file->ofs_ << '\n';
  815. for (const StaticFieldRegistration& staticField : processedClass.staticFields_)
  816. {
  817. const RegisterGlobalPropertyArgs& args = staticField.registration_;
  818. assert(args.asDeclarations_.size());
  819. for (const string& asDeclaration : args.asDeclarations_)
  820. file->ofs_ << " members.staticFields_.Push(RegisterGlobalPropertyArgs(\"" << staticField.cppDeclaration_ << "\", \"" << asDeclaration << "\", " << args.pointer_ << "));\n";
  821. file->needGap_ = true;
  822. }
  823. if (file->needGap_)
  824. file->ofs_ << '\n';
  825. //file->ofs_ <<
  826. // " #ifdef REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "\n"
  827. // " REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "();\n"
  828. // " #endif\n";
  829. file->ofs_ << "}\n";
  830. }
  831. for (auto it : memberCppFiles_)
  832. {
  833. shared_ptr<MemberCppFile> file = it.second;
  834. if (!file->openedDefine_.empty())
  835. {
  836. file->ofs_ <<
  837. "\n"
  838. "#endif // def " << file->openedDefine_ << "\n";
  839. file->openedDefine_.clear();
  840. }
  841. file->ofs_ <<
  842. "\n"
  843. "} // namespace Urho3D\n";
  844. }
  845. ofstream ofsH(_sourceDir + "/Source/Urho3D/AngelScript/GeneratedClassMembers.h");
  846. ofsH <<
  847. "// DO NOT EDIT. This file is generated\n"
  848. "\n"
  849. "#pragma once\n"
  850. "\n"
  851. "#include \"../AngelScript/APITemplates.h\"\n"
  852. "\n"
  853. "#include \"../AngelScript/GeneratedIncludes.h\"\n"
  854. "\n"
  855. "namespace Urho3D\n"
  856. "{\n";
  857. string openedDefine;
  858. for (const ProcessedClass& processedClass : classes_)
  859. {
  860. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  861. {
  862. ofsH <<
  863. "\n"
  864. "#endif // def " << openedDefine << "\n";
  865. openedDefine.clear();
  866. }
  867. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  868. {
  869. ofsH <<
  870. "\n"
  871. "#ifdef " << processedClass.insideDefine_ << "\n";
  872. openedDefine = processedClass.insideDefine_;
  873. }
  874. ofsH <<
  875. "\n"
  876. "// " << processedClass.comment_ << "\n"
  877. "void CollectMembers_" << processedClass.name_ << "(MemberCollection& members);\n";
  878. }
  879. if (!openedDefine.empty())
  880. {
  881. ofsH <<
  882. "\n"
  883. "#endif // def " << openedDefine << "\n";
  884. openedDefine.clear();
  885. }
  886. ofsH <<
  887. "\n"
  888. "} // namespace Urho3D\n";
  889. ofsH = ofstream(_sourceDir + "/Source/Urho3D/AngelScript/Generated_Members.h");
  890. ofsH <<
  891. "// DO NOT EDIT. This file is generated\n"
  892. "\n"
  893. "#pragma once\n"
  894. "\n"
  895. "#include \"../AngelScript/APITemplates.h\"\n"
  896. "\n"
  897. "#include \"../AngelScript/GeneratedIncludes.h\"\n"
  898. "#include \"../AngelScript/Manual.h\"\n"
  899. "\n"
  900. "namespace Urho3D\n"
  901. "{\n";
  902. openedDefine.clear();
  903. for (const ProcessedClass& processedClass : classes_)
  904. {
  905. if (processedClass.insideDefine_ != openedDefine && !openedDefine.empty())
  906. {
  907. ofsH <<
  908. "\n"
  909. "#endif // def " << openedDefine << "\n";
  910. openedDefine.clear();
  911. }
  912. if (processedClass.insideDefine_ != openedDefine && !processedClass.insideDefine_.empty())
  913. {
  914. ofsH <<
  915. "\n"
  916. "#ifdef " << processedClass.insideDefine_ << "\n";
  917. openedDefine = processedClass.insideDefine_;
  918. }
  919. for (const Registration& method : processedClass.templateMethods_)
  920. {
  921. if (method.glue_.size())
  922. {
  923. ofsH <<
  924. "\n"
  925. "// " << method.comment_ << "\n"
  926. << method.glue_;
  927. }
  928. }
  929. for (const Registration& staticMethod : processedClass.templateStaticMethods_)
  930. {
  931. if (staticMethod.glue_.size())
  932. {
  933. ofsH <<
  934. "\n"
  935. "// " << staticMethod.comment_ << "\n"
  936. << staticMethod.glue_;
  937. }
  938. }
  939. ofsH <<
  940. "\n"
  941. "// " << processedClass.comment_ << "\n"
  942. "template <class T> void RegisterMembers_" << processedClass.name_ << "(asIScriptEngine* engine, const char* className)\n"
  943. "{\n";
  944. bool needGap = false;
  945. if (processedClass.baseClassNames_.size())
  946. {
  947. for (const string& baseClassName : processedClass.baseClassNames_)
  948. ofsH << " RegisterMembers_" << baseClassName << "<T>(engine, className);\n";
  949. needGap = true;
  950. }
  951. if (needGap && processedClass.unregisteredMethods_.size())
  952. ofsH << '\n';
  953. for (const MemberRegistrationError& unregisteredMethod : processedClass.unregisteredMethods_)
  954. {
  955. ofsH <<
  956. " // " << unregisteredMethod.comment_ << "\n"
  957. " // " << unregisteredMethod.message_ << "\n";
  958. needGap = true;
  959. }
  960. for (const Registration& method : processedClass.templateMethods_)
  961. {
  962. if (needGap)
  963. ofsH << '\n';
  964. ofsH << " // " << method.comment_ << '\n';
  965. for (const string& registration : method.registration_)
  966. ofsH << " " << registration << '\n';
  967. needGap = true;
  968. }
  969. for (const Registration& staticMethod : processedClass.templateStaticMethods_)
  970. {
  971. if (needGap)
  972. ofsH << '\n';
  973. ofsH << " // " << staticMethod.comment_ << '\n';
  974. for (const string& registration : staticMethod.registration_)
  975. ofsH << " " << registration << '\n';
  976. needGap = true;
  977. }
  978. ofsH <<
  979. " #ifdef REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "\n"
  980. " REGISTER_MEMBERS_MANUAL_PART_" << processedClass.name_ << "();\n"
  981. " #endif\n";
  982. ofsH << "}\n";
  983. }
  984. if (!openedDefine.empty())
  985. {
  986. ofsH <<
  987. "\n"
  988. "#endif // def " << openedDefine << "\n";
  989. openedDefine.clear();
  990. }
  991. ofsH <<
  992. "\n"
  993. "} // namespace Urho3D\n";
  994. }
  995. static void SaveClasses()
  996. {
  997. sort(classes_.begin(), classes_.end());
  998. SaveObjectTypes();
  999. SaveDefaultConstructors();
  1000. SaveGeneratedClasses();
  1001. SaveClassMembers();
  1002. }
  1003. // ============================================================================
  1004. // List of all required header files
  1005. static vector<string> headers_;
  1006. // Discarded header files for statistic
  1007. static vector<string> ignoredHeaders_;
  1008. // Add header to lists if not added yet
  1009. void AddHeader(const string& headerFile)
  1010. {
  1011. if (IsIgnoredHeader(headerFile))
  1012. {
  1013. if (!CONTAINS(ignoredHeaders_, headerFile))
  1014. ignoredHeaders_.push_back(headerFile);
  1015. }
  1016. else
  1017. {
  1018. if (!CONTAINS(headers_, headerFile))
  1019. headers_.push_back(headerFile);
  1020. }
  1021. }
  1022. // Write result to GeneratedIncludes.h
  1023. static void SaveIncludes()
  1024. {
  1025. sort(headers_.begin(), headers_.end());
  1026. sort(ignoredHeaders_.begin(), ignoredHeaders_.end());
  1027. ofstream ofs(_sourceDir + "/Source/Urho3D/AngelScript/GeneratedIncludes.h");
  1028. ofs <<
  1029. "// DO NOT EDIT. This file is generated\n"
  1030. "\n"
  1031. "#pragma once\n"
  1032. "\n";
  1033. string openedDefine;
  1034. bool isFirst = true;
  1035. for (const string& header : headers_)
  1036. {
  1037. string insideDefine = InsideDefine(header);
  1038. if (insideDefine != openedDefine)
  1039. {
  1040. if (!openedDefine.empty())
  1041. {
  1042. ofs << "#endif\n";
  1043. openedDefine.clear();
  1044. }
  1045. if (!isFirst) // First include can be guarded. Avoid print \n before it
  1046. ofs << "\n";
  1047. if (!insideDefine.empty())
  1048. {
  1049. ofs << "#ifdef " << insideDefine << "\n";
  1050. openedDefine = insideDefine;
  1051. }
  1052. }
  1053. ofs << "#include \"" << header << "\"\n";
  1054. isFirst = false;
  1055. }
  1056. if (!openedDefine.empty())
  1057. {
  1058. ofs << "#endif\n";
  1059. openedDefine.clear();
  1060. }
  1061. if (headers_.size() > 0)
  1062. ofs << "\n";
  1063. if (ignoredHeaders_.size() > 0)
  1064. ofs << "// Ignored headers\n\n";
  1065. isFirst = true;
  1066. for (const string& header : ignoredHeaders_)
  1067. {
  1068. string insideDefine = InsideDefine(header);
  1069. if (insideDefine != openedDefine)
  1070. {
  1071. if (!openedDefine.empty())
  1072. {
  1073. ofs << "//#endif\n";
  1074. openedDefine.clear();
  1075. }
  1076. if (!isFirst) // First include can be guarded. Avoid print \n before it
  1077. ofs << "\n";
  1078. if (!insideDefine.empty())
  1079. {
  1080. ofs << "//#ifdef " << insideDefine << "\n";
  1081. openedDefine = insideDefine;
  1082. }
  1083. }
  1084. ofs << "//#include \"" << header << "\"\n";
  1085. isFirst = false;
  1086. }
  1087. if (!openedDefine.empty())
  1088. ofs << "//#endif\n";
  1089. }
  1090. }
  1091. void SaveResult()
  1092. {
  1093. Result::SaveEnums();
  1094. Result::SaveGlobalFunctions();
  1095. Result::SaveGlobalVariables();
  1096. Result::SaveClasses();
  1097. Result::SaveIncludes();
  1098. }
  1099. }