ASClassBinder.cpp 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  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 "ASUtils.h"
  24. #include "Tuning.h"
  25. #include "Utils.h"
  26. #include "XmlAnalyzer.h"
  27. #include "XmlSourceData.h"
  28. #include <cassert>
  29. #include <fstream>
  30. #include <iostream>
  31. #include <regex>
  32. #include <vector>
  33. #include <unordered_map>
  34. #include <unordered_set>
  35. namespace ASBindingGenerator
  36. {
  37. static void RegisterObjectType(const ClassAnalyzer& classAnalyzer, ProcessedClass& inoutProcessedClass)
  38. {
  39. string className = classAnalyzer.GetClassName();
  40. bool isNoCount = classAnalyzer.IsNoCount();
  41. if (classAnalyzer.IsRefCounted() || isNoCount)
  42. {
  43. inoutProcessedClass.objectTypeRegistration_ = "engine->RegisterObjectType(\"" + className + "\", 0, asOBJ_REF" +
  44. (isNoCount ? " | asOBJ_NOCOUNT" : "") + ");";
  45. }
  46. else // Value type
  47. {
  48. string flags = "asOBJ_VALUE | asGetTypeTraits<" + className + ">()";
  49. if (classAnalyzer.IsPod())
  50. {
  51. flags += " | asOBJ_POD";
  52. if (classAnalyzer.AllFloats())
  53. flags += " | asOBJ_APP_CLASS_ALLFLOATS";
  54. else if (classAnalyzer.AllInts())
  55. flags += " | asOBJ_APP_CLASS_ALLINTS";
  56. }
  57. inoutProcessedClass.objectTypeRegistration_ = "engine->RegisterObjectType(\"" + className + "\", sizeof(" + className + "), " + flags + ");";
  58. }
  59. }
  60. static bool IsConstructorRequired(const ClassAnalyzer& classAnalyzer)
  61. {
  62. if (classAnalyzer.IsRefCounted())
  63. return false;
  64. if (classAnalyzer.IsNoCount())
  65. return false;
  66. if (classAnalyzer.IsPod())
  67. return false;
  68. return true;
  69. }
  70. static bool IsDestructorRequired(const ClassAnalyzer& classAnalyzer)
  71. {
  72. if (classAnalyzer.IsRefCounted())
  73. return false;
  74. if (classAnalyzer.IsNoCount())
  75. return false;
  76. if (classAnalyzer.IsPod())
  77. return false;
  78. return true;
  79. }
  80. // Iterate over overrided funcions
  81. static bool HaveMark(const MethodAnalyzer& methodAnalyzer, const string& mark)
  82. {
  83. if (Contains(methodAnalyzer.GetComment(), mark))
  84. return true;
  85. shared_ptr<MethodAnalyzer> reimplements = methodAnalyzer.Reimplements();
  86. if (!reimplements)
  87. return false;
  88. return HaveMark(*reimplements, mark);
  89. }
  90. static void RegisterConstructor(const MethodAnalyzer& methodAnalyzer, ProcessedClass& processedClass)
  91. {
  92. ClassAnalyzer classAnalyzer = methodAnalyzer.GetClass();
  93. if (classAnalyzer.IsAbstract())
  94. return;
  95. if (methodAnalyzer.IsDeleted())
  96. {
  97. MemberRegistrationError regError;
  98. regError.name_ = methodAnalyzer.GetName();
  99. regError.comment_ = methodAnalyzer.GetDeclaration();
  100. regError.message_ = "Not registered because deleted";
  101. processedClass.unregisteredSpecialMethods_.push_back(regError);
  102. return;
  103. }
  104. if (HaveMark(methodAnalyzer, "NO_BIND"))
  105. {
  106. MemberRegistrationError regError;
  107. regError.name_ = methodAnalyzer.GetName();
  108. regError.comment_ = methodAnalyzer.GetDeclaration();
  109. regError.message_ = "Not registered because have @nobind mark";
  110. processedClass.unregisteredSpecialMethods_.push_back(regError);
  111. return;
  112. }
  113. if (HaveMark(methodAnalyzer, "MANUAL_BIND"))
  114. {
  115. MemberRegistrationError regError;
  116. regError.name_ = methodAnalyzer.GetName();
  117. regError.comment_ = methodAnalyzer.GetDeclaration();
  118. regError.message_ = "Not registered because have @manualbind mark";
  119. processedClass.unregisteredSpecialMethods_.push_back(regError);
  120. return;
  121. }
  122. SpecialMethodRegistration result;
  123. //result.name_ = methodAnalyzer.GetName();
  124. result.comment_ = methodAnalyzer.GetDeclaration();
  125. string asClassName = classAnalyzer.GetClassName();
  126. string cppClassName = classAnalyzer.GetClassName();
  127. vector<ParamAnalyzer> params = methodAnalyzer.GetParams();
  128. bool isNoCount = classAnalyzer.IsNoCount();
  129. if (params.empty()) // Default constructor
  130. {
  131. if (classAnalyzer.IsRefCounted() || isNoCount)
  132. result.registration_ = "engine->RegisterObjectBehaviour(\"" + asClassName + "\", asBEHAVE_FACTORY, \"" +
  133. asClassName + "@" + (isNoCount ? "" : "+") +
  134. " f()\", asFUNCTION(ASCompatibleFactory<" + cppClassName + ">), AS_CALL_CDECL);";
  135. else
  136. result.registration_ = "engine->RegisterObjectBehaviour(\"" + asClassName + "\", asBEHAVE_CONSTRUCT, \"void f()\", asFUNCTION(ASCompatibleConstructor<" + cppClassName + ">), AS_CALL_CDECL_OBJFIRST);";
  137. result.comment_ = methodAnalyzer.GetLocation(); // Rewrite comment
  138. processedClass.defaultConstructor_ = make_shared<SpecialMethodRegistration>(result);
  139. return;
  140. }
  141. vector<ConvertedVariable> convertedParams;
  142. for (const ParamAnalyzer& param : params)
  143. {
  144. ConvertedVariable convertedParam;
  145. try
  146. {
  147. convertedParam = CppVariableToAS(param.GetType(), VariableUsage::FunctionParameter, param.GetDeclname(), param.GetDefval());
  148. }
  149. catch (const Exception& e)
  150. {
  151. MemberRegistrationError regError;
  152. regError.name_ = methodAnalyzer.GetName();
  153. regError.comment_ = methodAnalyzer.GetDeclaration();
  154. regError.message_ = e.what();
  155. processedClass.unregisteredSpecialMethods_.push_back(regError);
  156. return;
  157. }
  158. convertedParams.push_back(convertedParam);
  159. }
  160. bool needWrapper = false;
  161. for (const ConvertedVariable& convertedParam : convertedParams)
  162. {
  163. if (convertedParam.NeedWrapper())
  164. needWrapper = true;
  165. }
  166. if (classAnalyzer.IsRefCounted() || isNoCount)
  167. {
  168. string asDeclaration = asClassName + "@" + (isNoCount ? "" : "+") + " f(" + JoinASDeclarations(convertedParams) + ")";
  169. result.registration_ = result.registration_ =
  170. "engine->RegisterObjectBehaviour(\"" + asClassName + "\", asBEHAVE_FACTORY, \"" + asDeclaration + "\", AS_FUNCTION("
  171. + GenerateWrapperName(methodAnalyzer) + ") , AS_CALL_CDECL);";
  172. result.glue_ = GenerateFactoryWrapper(methodAnalyzer, convertedParams);
  173. }
  174. else
  175. {
  176. string asDeclaration = "void f(" + JoinASDeclarations(convertedParams) + ")";
  177. result.registration_ = "engine->RegisterObjectBehaviour(\"" + asClassName + "\", asBEHAVE_CONSTRUCT, \"" + asDeclaration +
  178. "\", AS_FUNCTION_OBJFIRST(" + GenerateWrapperName(methodAnalyzer) + "), AS_CALL_CDECL_OBJFIRST);";
  179. result.glue_ = GenerateConstructorWrapper(methodAnalyzer, convertedParams);
  180. }
  181. processedClass.nonDefaultConstructors_.push_back(result);
  182. }
  183. static void RegisterDestructor(const ClassAnalyzer& classAnalyzer, ProcessedClass& processedClass)
  184. {
  185. if (classAnalyzer.IsRefCounted())
  186. return;
  187. if (classAnalyzer.IsNoCount())
  188. return;
  189. string className = classAnalyzer.GetClassName();
  190. string wrapperName = className + "_Destructor";
  191. shared_ptr<SpecialMethodRegistration> result = make_shared<SpecialMethodRegistration>();
  192. //result->name_ = "~" + className;
  193. result->registration_ = "engine->RegisterObjectBehaviour(\"" + className + "\", asBEHAVE_DESTRUCT, \"void f()\", AS_DESTRUCTOR(" + className + "), AS_CALL_CDECL_OBJFIRST);";
  194. shared_ptr<MethodAnalyzer> thisDestructor = classAnalyzer.GetDefinedThisDestructor();
  195. if (thisDestructor)
  196. {
  197. result->comment_ = thisDestructor->GetDeclaration();
  198. processedClass.destructor_ = result;
  199. }
  200. else if (!classAnalyzer.HasThisDestructor() && IsDestructorRequired(classAnalyzer))
  201. {
  202. result->comment_ = className + "::~" + className + "() | Implicitly-declared";
  203. processedClass.destructor_ = result;
  204. }
  205. }
  206. // https://www.angelcode.com/angelscript/sdk/docs/manual/doc_script_class_ops.html
  207. static string CppMethodNameToAS(const MethodAnalyzer& methodAnalyzer)
  208. {
  209. string name = methodAnalyzer.GetName();
  210. if (name == "operator=")
  211. return "opAssign";
  212. if (name == "operator+")
  213. return "opAdd";
  214. if (name == "operator-")
  215. {
  216. if (!methodAnalyzer.GetParams().size()) // If no params
  217. return "opNeg"; // then unary minus
  218. else
  219. return "opSub";
  220. }
  221. if (name == "operator*")
  222. return "opMul";
  223. if (name == "operator/")
  224. return "opDiv";
  225. if (name == "operator+=")
  226. return "opAddAssign";
  227. if (name == "operator-=")
  228. return "opSubAssign";
  229. if (name == "operator*=")
  230. return "opMulAssign";
  231. if (name == "operator/=")
  232. return "opDivAssign";
  233. if (name == "operator==")
  234. return "opEquals";
  235. if (name == "operator[]")
  236. return "opIndex";
  237. // Conversion to another type operator
  238. if (StartsWith(name, "operator "))
  239. {
  240. if (methodAnalyzer.IsExplicit())
  241. return "opConv";
  242. else
  243. return "opImplConv";
  244. }
  245. if (name == "operator!=")
  246. throw Exception("Only operator == is needed");
  247. if (name == "operator<")
  248. throw Exception("Registerd as opCmp separately");
  249. if (name == "operator>")
  250. throw Exception("Registerd as opCmp separately");
  251. return name;
  252. }
  253. // https://www.angelcode.com/angelscript/sdk/docs/manual/doc_reg_objprop.html
  254. static string CppMethodNameToASProperty(const MethodAnalyzer& methodAnalyzer)
  255. {
  256. string name = methodAnalyzer.GetName();
  257. if (StartsWith(name, "Is") || StartsWith(name, "Get"))
  258. {
  259. string result = CutStart(name, "Is");
  260. result = CutStart(result, "Get");
  261. result = "get_" + FirstCharToLower(result);
  262. return result;
  263. }
  264. if (StartsWith(name, "Set"))
  265. {
  266. string result = CutStart(name, "Set");
  267. result = "set_" + FirstCharToLower(result);
  268. return result;
  269. }
  270. if (methodAnalyzer.CanBeGetProperty())
  271. {
  272. string result = name;
  273. result = "get_" + FirstCharToLower(result);
  274. return result;
  275. }
  276. if (methodAnalyzer.CanBeSetProperty())
  277. {
  278. string result = name;
  279. result = "set_" + FirstCharToLower(result);
  280. return result;
  281. }
  282. throw Exception("Can not be property");
  283. }
  284. // Can return BIND_AS_ALIAS_xxxx or BIND_AS_PROPERTY
  285. // Return "" if no this marks
  286. static string GetPropertyMark(const MethodAnalyzer& methodAnalyzer)
  287. {
  288. string comment = methodAnalyzer.GetComment();
  289. smatch match;
  290. regex_match(comment, match, regex(".*\\b(BIND_AS_ALIAS_.+?)\\b.*"));
  291. if (match.size() == 2)
  292. return match[1].str();
  293. regex_match(comment, match, regex(".*\\bBIND_AS_PROPERTY\\b.*"));
  294. if (match.size() == 1)
  295. return "BIND_AS_PROPERTY";
  296. shared_ptr<MethodAnalyzer> reimplements = methodAnalyzer.Reimplements();
  297. if (!reimplements)
  298. return "";
  299. return GetPropertyMark(*reimplements);
  300. }
  301. static string GetSignature(const MethodAnalyzer& method)
  302. {
  303. xml_node memberdef = method.GetMemberdef();
  304. string result = string(memberdef.child_value("name")) + '|';
  305. result += RemoveRefs(memberdef.child("type")) + '|';
  306. for (xml_node param : memberdef.children("param"))
  307. result += RemoveRefs(param.child("type")) + '|';
  308. if (method.IsStatic())
  309. result += "static" + result;
  310. return result;
  311. }
  312. struct ClassMemberSignatures
  313. {
  314. unordered_set<string> methods_; // Signatures of all nonstatic public methods (including inherited)
  315. unordered_map<string, vector<string>> hiddenInAnyDerivedClassesMethods_; // method signature -> derived class names
  316. unordered_map<string, vector<string>> existsInBaseClassesMethods_; // method signature -> base class names
  317. };
  318. static unordered_map<string, shared_ptr<ClassMemberSignatures>> _cachedMemberSignatures; // className -> signatures
  319. static bool ContainsSameSignature(const string& className, const string& methodSignature)
  320. {
  321. shared_ptr<ClassMemberSignatures> classData = _cachedMemberSignatures[className];
  322. return classData->methods_.find(methodSignature) != classData->methods_.end();
  323. }
  324. static void InitCachedMemberSignatures()
  325. {
  326. // Fill signatures
  327. for (auto element : SourceData::classesByID_)
  328. {
  329. xml_node compounddef = element.second;
  330. ClassAnalyzer classAnalyzer(compounddef);
  331. shared_ptr<ClassMemberSignatures> classData = make_shared<ClassMemberSignatures>();
  332. vector<MethodAnalyzer> methods = classAnalyzer.GetAllPublicMethods();
  333. for (const MethodAnalyzer& method : methods)
  334. classData->methods_.insert(GetSignature(method));
  335. _cachedMemberSignatures[classAnalyzer.GetClassName()] = classData;
  336. }
  337. // Fill hidden in any derived classes members
  338. for (auto element : SourceData::classesByID_)
  339. {
  340. xml_node compounddef = element.second;
  341. ClassAnalyzer classAnalyzer(compounddef);
  342. string className = classAnalyzer.GetClassName();
  343. shared_ptr<ClassMemberSignatures> classData = _cachedMemberSignatures[classAnalyzer.GetClassName()];
  344. vector<MethodAnalyzer> methods = classAnalyzer.GetAllPublicMethods();
  345. vector<ClassAnalyzer> allDerivedClasses = classAnalyzer.GetAllDerivedClasses();
  346. vector<ClassAnalyzer> baseClasses = classAnalyzer.GetBaseClasses();
  347. for (const MethodAnalyzer& method : methods)
  348. {
  349. string methodSignature = GetSignature(method);
  350. vector<string> hiddenInderivedClasses;
  351. for (const ClassAnalyzer& derivedClass : allDerivedClasses)
  352. {
  353. string derivedClassName = derivedClass.GetClassName();
  354. if (!ContainsSameSignature(derivedClassName, methodSignature))
  355. hiddenInderivedClasses.push_back(derivedClassName);
  356. }
  357. if (hiddenInderivedClasses.size())
  358. classData->hiddenInAnyDerivedClassesMethods_[methodSignature] = hiddenInderivedClasses;
  359. vector<string> existInBaseClasses;
  360. for (const ClassAnalyzer& baseClass : baseClasses)
  361. {
  362. string baseClassName = baseClass.GetClassName();
  363. if (ContainsSameSignature(baseClassName, methodSignature))
  364. existInBaseClasses.push_back(baseClassName);
  365. }
  366. if (existInBaseClasses.size())
  367. classData->existsInBaseClassesMethods_[methodSignature] = existInBaseClasses;
  368. }
  369. }
  370. }
  371. /*static bool ContainsSameSignature(const ClassAnalyzer& classAnalyzer, const MethodAnalyzer& method)
  372. {
  373. vector<MethodAnalyzer> methods = classAnalyzer.GetAllPublicMethods();
  374. for (const MethodAnalyzer& m : methods)
  375. {
  376. if (GetSignature(m) == GetSignature(method))
  377. return true;
  378. }
  379. return false;
  380. }*/
  381. static vector<string> HiddenInAnyDerivedClasses(const MethodAnalyzer& method)
  382. {
  383. /*vector<string> result;
  384. vector<ClassAnalyzer> derivedClasses = method.GetClass().GetAllDerivedClasses();
  385. for (const ClassAnalyzer& derivedClass : derivedClasses)
  386. {
  387. //if (!ContainsSameSignature(derivedClass, method))
  388. // result.push_back(derivedClass.GetClassName());
  389. if (!ContainsSameSignature(derivedClass.GetClassName(), GetSignature(method)))
  390. result.push_back(derivedClass.GetClassName());
  391. }
  392. return result;*/
  393. string classname = method.GetClassName();
  394. string methodSignature = GetSignature(method);
  395. shared_ptr<ClassMemberSignatures> classData = _cachedMemberSignatures[classname];
  396. auto it = classData->hiddenInAnyDerivedClassesMethods_.find(methodSignature);
  397. if (it == classData->hiddenInAnyDerivedClassesMethods_.end())
  398. return vector<string>();
  399. else
  400. return it->second;
  401. }
  402. static vector<string> HiddenInAnyDerivedClasses(const MethodAnalyzer& method, const ClassAnalyzer& classAnalyzer)
  403. {
  404. /*vector<string> result;
  405. vector<ClassAnalyzer> derivedClasses = classAnalyzer.GetAllDerivedClasses();
  406. for (const ClassAnalyzer& derivedClass : derivedClasses)
  407. {
  408. //if (!ContainsSameSignature(derivedClass, method))
  409. // result.push_back(derivedClass.GetClassName());
  410. if (!ContainsSameSignature(derivedClass.GetClassName(), GetSignature(method)))
  411. result.push_back(derivedClass.GetClassName());
  412. }
  413. return result;*/
  414. string classname = classAnalyzer.GetClassName();
  415. string methodSignature = GetSignature(method);
  416. shared_ptr<ClassMemberSignatures> classData = _cachedMemberSignatures[classname];
  417. auto it = classData->hiddenInAnyDerivedClassesMethods_.find(methodSignature);
  418. if (it == classData->hiddenInAnyDerivedClassesMethods_.end())
  419. return vector<string>();
  420. else
  421. return it->second;
  422. }
  423. static vector<string> ExistsInBaseClasses(const MethodAnalyzer& method)
  424. {
  425. /*vector<string> result;
  426. vector<ClassAnalyzer> baseClasses = method.GetClass().GetBaseClasses();
  427. string methodSignature = GetSignature(method);
  428. for (const ClassAnalyzer& baseClass : baseClasses)
  429. {
  430. //if (ContainsSameSignature(baseClass, method))
  431. // result.push_back(baseClass.GetClassName());
  432. if (ContainsSameSignature(baseClass.GetClassName(), methodSignature))
  433. result.push_back(baseClass.GetClassName());
  434. }
  435. return result;*/
  436. string classname = method.GetClassName();
  437. string methodSignature = GetSignature(method);
  438. shared_ptr<ClassMemberSignatures> classData = _cachedMemberSignatures[classname];
  439. auto it = classData->existsInBaseClassesMethods_.find(methodSignature);
  440. if (it == classData->existsInBaseClassesMethods_.end())
  441. return vector<string>();
  442. else
  443. return it->second;
  444. }
  445. static vector<string> ExistsInBaseClasses(const MethodAnalyzer& method, const ClassAnalyzer& classAnalyzer)
  446. {
  447. /*vector<string> result;
  448. vector<ClassAnalyzer> baseClasses = classAnalyzer.GetBaseClasses();
  449. string methodSignature = GetSignature(method);
  450. for (const ClassAnalyzer& baseClass : baseClasses)
  451. {
  452. //if (ContainsSameSignature(baseClass, method))
  453. // result.push_back(baseClass.GetClassName());
  454. if (ContainsSameSignature(baseClass.GetClassName(), methodSignature))
  455. result.push_back(baseClass.GetClassName());
  456. }
  457. return result;*/
  458. string className = classAnalyzer.GetClassName();
  459. string methodSignature = GetSignature(method);
  460. shared_ptr<ClassMemberSignatures> classData = _cachedMemberSignatures[className];
  461. auto it = classData->existsInBaseClassesMethods_.find(methodSignature);
  462. if (it == classData->existsInBaseClassesMethods_.end())
  463. return vector<string>();
  464. else
  465. return it->second;
  466. }
  467. // Returns names of derived class that has base classes with the same method signature
  468. // (multiple inheriance methods with same signature - we can not register this in template because this cause multiple registration same signature)
  469. static string FindConflicts(const MethodAnalyzer& method)
  470. {
  471. vector<ClassAnalyzer> derivedClasses = method.GetClass().GetAllDerivedClasses();
  472. for (const ClassAnalyzer& derivedClass : derivedClasses)
  473. {
  474. vector<string> existsInBaseClasses = ExistsInBaseClasses(method, derivedClass);
  475. if (existsInBaseClasses.size() > 1)
  476. return derivedClass.GetClassName(); // Conflict found
  477. }
  478. return string(); // No conflicts
  479. }
  480. static string FindConflicts(const MethodAnalyzer& method, const ClassAnalyzer& classAnalyzer)
  481. {
  482. vector<ClassAnalyzer> derivedClasses = classAnalyzer.GetAllDerivedClasses();
  483. for (const ClassAnalyzer& derivedClass : derivedClasses)
  484. {
  485. vector<string> existsInBaseClasses = ExistsInBaseClasses(method, derivedClass);
  486. if (existsInBaseClasses.size() > 1)
  487. return derivedClass.GetClassName(); // Conflict found
  488. }
  489. return string(); // No conflicts
  490. }
  491. static void RegisterMethod(const MethodAnalyzer& methodAnalyzer, ProcessedClass& processedClass)
  492. {
  493. if (methodAnalyzer.IsDefine())
  494. return;
  495. // TEST
  496. //if (/*methodAnalyzer.GetClassName() == "OcclusionBuffer" && */methodAnalyzer.GetName() == "AddRef")
  497. // string className = methodAnalyzer.GetClassName(); // Breakpoint here
  498. // TEST END
  499. // TODO: This functions take 99% of generation time. Need some cache?
  500. // ===============================================
  501. vector<string> existsInBaseClasses = ExistsInBaseClasses(methodAnalyzer);
  502. if (existsInBaseClasses.size() == 1)
  503. {
  504. shared_ptr<ClassAnalyzer> baseClass = FindClassByName(existsInBaseClasses[0]);
  505. if (HiddenInAnyDerivedClasses(methodAnalyzer, *baseClass).empty() && FindConflicts(methodAnalyzer, *baseClass).empty())
  506. return; // Already registered in template of base class
  507. }
  508. bool regInTemplate = true;
  509. vector<string> hiddenInDerivedClasses = HiddenInAnyDerivedClasses(methodAnalyzer);
  510. if (!hiddenInDerivedClasses.empty())
  511. {
  512. if (methodAnalyzer.IsThisMethod())
  513. {
  514. MemberRegistrationError msg;
  515. msg.name_ = methodAnalyzer.GetName();
  516. msg.comment_ = methodAnalyzer.GetDeclaration();
  517. msg.message_ = "Can not be registered here bacause hidden in derived classes: " + Join(hiddenInDerivedClasses, ", ");
  518. processedClass.unregisteredTemplateMethods_.push_back(msg);
  519. }
  520. regInTemplate = false; // Impossible register in template
  521. }
  522. if (regInTemplate) // Additional check
  523. {
  524. string conflict = FindConflicts(methodAnalyzer);
  525. if (!conflict.empty())
  526. regInTemplate = false; // Impossible register in tempalte
  527. }
  528. // ====================================================
  529. // END
  530. if (methodAnalyzer.IsTemplate())
  531. {
  532. MemberRegistrationError regError;
  533. regError.name_ = methodAnalyzer.GetName();
  534. regError.comment_ = methodAnalyzer.GetDeclaration();
  535. regError.message_ = "Not registered because template";
  536. if (regInTemplate)
  537. processedClass.unregisteredTemplateStaticMethods_.push_back(regError);
  538. else
  539. processedClass.unregisteredPersonalStaticMethods_.push_back(regError);
  540. return;
  541. }
  542. if (methodAnalyzer.IsDeleted())
  543. {
  544. MemberRegistrationError regError;
  545. regError.name_ = methodAnalyzer.GetName();
  546. regError.comment_ = methodAnalyzer.GetDeclaration();
  547. regError.message_ = "Not registered because deleted";
  548. if (regInTemplate)
  549. processedClass.unregisteredTemplateStaticMethods_.push_back(regError);
  550. else
  551. processedClass.unregisteredPersonalStaticMethods_.push_back(regError);
  552. return;
  553. }
  554. if (methodAnalyzer.IsStatic())
  555. {
  556. if (HaveMark(methodAnalyzer, "NO_BIND"))
  557. {
  558. MemberRegistrationError regError;
  559. regError.name_ = methodAnalyzer.GetName();
  560. regError.comment_ = methodAnalyzer.GetDeclaration();
  561. regError.message_ = "Not registered because have @nobind mark";
  562. if (regInTemplate)
  563. processedClass.unregisteredTemplateStaticMethods_.push_back(regError);
  564. else
  565. processedClass.unregisteredPersonalStaticMethods_.push_back(regError);
  566. return;
  567. }
  568. if (HaveMark(methodAnalyzer, "MANUAL_BIND"))
  569. {
  570. MemberRegistrationError regError;
  571. regError.name_ = methodAnalyzer.GetName();
  572. regError.comment_ = methodAnalyzer.GetDeclaration();
  573. regError.message_ = "Not registered because have @manualbind mark";
  574. if (regInTemplate)
  575. processedClass.unregisteredTemplateStaticMethods_.push_back(regError);
  576. else
  577. processedClass.unregisteredPersonalStaticMethods_.push_back(regError);
  578. return;
  579. }
  580. ClassStaticFunctionAnalyzer staticMethodAnalyzer(methodAnalyzer.GetClass(), methodAnalyzer.GetMemberdef());
  581. vector<ParamAnalyzer> params = staticMethodAnalyzer.GetParams();
  582. vector<ConvertedVariable> convertedParams;
  583. string outGlue;
  584. bool needWrapper = false;
  585. for (const ParamAnalyzer& param : params)
  586. {
  587. ConvertedVariable conv;
  588. try
  589. {
  590. conv = CppVariableToAS(param.GetType(), VariableUsage::FunctionParameter, param.GetDeclname(), param.GetDefval());
  591. }
  592. catch (const Exception& e)
  593. {
  594. MemberRegistrationError regError;
  595. regError.name_ = staticMethodAnalyzer.GetName();
  596. regError.comment_ = methodAnalyzer.GetDeclaration();
  597. regError.message_ = e.what();
  598. if (regInTemplate)
  599. processedClass.unregisteredTemplateStaticMethods_.push_back(regError);
  600. else
  601. processedClass.unregisteredPersonalStaticMethods_.push_back(regError);
  602. return;
  603. }
  604. if (conv.NeedWrapper())
  605. needWrapper = true;
  606. convertedParams.push_back(conv);
  607. }
  608. ConvertedVariable convertedReturn;
  609. try
  610. {
  611. convertedReturn = CppVariableToAS(staticMethodAnalyzer.GetReturnType(), VariableUsage::FunctionReturn);
  612. }
  613. catch (const Exception& e)
  614. {
  615. MemberRegistrationError regError;
  616. regError.name_ = staticMethodAnalyzer.GetName();
  617. regError.comment_ = methodAnalyzer.GetDeclaration();
  618. regError.message_ = e.what();
  619. if (regInTemplate)
  620. processedClass.unregisteredTemplateStaticMethods_.push_back(regError);
  621. else
  622. processedClass.unregisteredPersonalStaticMethods_.push_back(regError);
  623. return;
  624. }
  625. if (convertedReturn.NeedWrapper())
  626. needWrapper = true;
  627. Registration result;
  628. result.comment_ = methodAnalyzer.GetDeclaration();
  629. string funcPointer;
  630. string callConv = "AS_CALL_CDECL";
  631. string asFunctionName = staticMethodAnalyzer.GetName();
  632. string cppClassName = methodAnalyzer.GetClass().GetClassName();
  633. string className = staticMethodAnalyzer.GetClassName();
  634. if (needWrapper)
  635. {
  636. /*result.glue_ = GenerateWrapper(methodAnalyzer, false, convertedParams, retConv);
  637. result.registration_.funcPointer_ = "AS_FUNCTION_OBJFIRST(" + GenerateWrapperName(methodAnalyzer) + ")";
  638. result.registration_.callConv_ = "AS_CALL_CDECL_OBJFIRST";*/
  639. result.glue_ = GenerateWrapper(staticMethodAnalyzer, regInTemplate, convertedParams, convertedReturn);
  640. funcPointer = "AS_FUNCTION(" + GenerateWrapperName(staticMethodAnalyzer);
  641. if (regInTemplate)
  642. funcPointer += "<" + cppClassName + ">";
  643. funcPointer += ")";
  644. }
  645. else
  646. {
  647. /*result.registration_.funcPointer_ = Generate_asMETHODPR(methodAnalyzer, regInTemplate);
  648. result.registration_.callConv_ = "AS_CALL_THISCALL";*/
  649. funcPointer = Generate_asFUNCTIONPR(staticMethodAnalyzer, regInTemplate);
  650. }
  651. string asClassName = cppClassName;
  652. string decl = convertedReturn.asDeclaration_ + " " + asFunctionName + "(" + JoinASDeclarations(convertedParams) + ")";
  653. if (regInTemplate)
  654. {
  655. result.registration_.push_back(
  656. "engine->SetDefaultNamespace(className);"
  657. "engine->RegisterGlobalFunction(\"" + decl + "\", " + funcPointer + ", " + callConv + ");"
  658. "engine->SetDefaultNamespace(\"\");"
  659. );
  660. }
  661. else
  662. {
  663. result.registration_.push_back(
  664. "engine->SetDefaultNamespace(\"" + asClassName + "\");"
  665. "engine->RegisterGlobalFunction(\"" + decl + "\", " + funcPointer + ", " + callConv + ");"
  666. "engine->SetDefaultNamespace(\"\");"
  667. );
  668. }
  669. /*
  670. StaticMethodRegistration result;
  671. result.cppDeclaration_ = methodAnalyzer.GetDeclaration();
  672. result.name_ = staticMethodAnalyzer.GetName();
  673. result.registration_.asDeclarations_.push_back(decl);
  674. result.registration_.callConv_ = "AS_CALL_CDECL";
  675. if (needWrapper)
  676. result.registration_.funcPointer_ = "AS_FUNCTION(" + GenerateWrapperName(staticMethodAnalyzer) + ")";
  677. else
  678. result.registration_.funcPointer_ = Generate_asFUNCTIONPR(staticMethodAnalyzer);
  679. if (needWrapper)
  680. result.glue_ = GenerateWrapper(staticMethodAnalyzer, convertedParams, convertedReturn);
  681. processedClass.staticMethods_.push_back(result);
  682. */
  683. if (regInTemplate)
  684. processedClass.templateStaticMethods_.push_back(result);
  685. else
  686. processedClass.personalStaticMethods_.push_back(result);
  687. return;
  688. }
  689. if (HaveMark(methodAnalyzer, "NO_BIND"))
  690. {
  691. MemberRegistrationError regError;
  692. regError.name_ = methodAnalyzer.GetName();
  693. regError.comment_ = methodAnalyzer.GetDeclaration();
  694. regError.message_ = "Not registered because have @nobind mark";
  695. if (regInTemplate)
  696. processedClass.unregisteredTemplateMethods_.push_back(regError);
  697. else
  698. processedClass.unregisteredPersonalMethods_.push_back(regError);
  699. return;
  700. }
  701. if (HaveMark(methodAnalyzer, "MANUAL_BIND"))
  702. {
  703. MemberRegistrationError regError;
  704. regError.name_ = methodAnalyzer.GetName();
  705. regError.comment_ = methodAnalyzer.GetDeclaration();
  706. regError.message_ = "Not registered because have @manualbind mark";
  707. if (regInTemplate)
  708. processedClass.unregisteredTemplateMethods_.push_back(regError);
  709. else
  710. processedClass.unregisteredPersonalMethods_.push_back(regError);
  711. return;
  712. }
  713. vector<ParamAnalyzer> params = methodAnalyzer.GetParams();
  714. vector<ConvertedVariable> convertedParams;
  715. bool needWrapper = false;
  716. for (const ParamAnalyzer& param : params)
  717. {
  718. ConvertedVariable conv;
  719. try
  720. {
  721. conv = CppVariableToAS(param.GetType(), VariableUsage::FunctionParameter, param.GetDeclname(), param.GetDefval());
  722. }
  723. catch (const Exception& e)
  724. {
  725. MemberRegistrationError regError;
  726. regError.name_ = methodAnalyzer.GetName();
  727. regError.comment_ = methodAnalyzer.GetDeclaration();
  728. regError.message_ = e.what();
  729. if (regInTemplate)
  730. processedClass.unregisteredTemplateMethods_.push_back(regError);
  731. else
  732. processedClass.unregisteredPersonalMethods_.push_back(regError);
  733. return;
  734. }
  735. convertedParams.push_back(conv);
  736. if (conv.NeedWrapper())
  737. needWrapper = true;
  738. }
  739. ConvertedVariable retConv;
  740. try
  741. {
  742. retConv = CppVariableToAS(methodAnalyzer.GetReturnType(), VariableUsage::FunctionReturn);
  743. }
  744. catch (const Exception& e)
  745. {
  746. MemberRegistrationError regError;
  747. regError.name_ = methodAnalyzer.GetName();
  748. regError.comment_ = methodAnalyzer.GetDeclaration();
  749. regError.message_ = e.what();
  750. if (regInTemplate)
  751. processedClass.unregisteredTemplateMethods_.push_back(regError);
  752. else
  753. processedClass.unregisteredPersonalMethods_.push_back(regError);
  754. return;
  755. }
  756. if (retConv.NeedWrapper())
  757. needWrapper = true;
  758. string asReturnType = retConv.asDeclaration_;
  759. string asFunctionName = methodAnalyzer.GetName();
  760. if (methodAnalyzer.IsConsversionOperator())
  761. asReturnType = CutStart(asFunctionName, "operator ");
  762. try
  763. {
  764. asFunctionName = CppMethodNameToAS(methodAnalyzer);
  765. }
  766. catch (const Exception& e)
  767. {
  768. MemberRegistrationError regError;
  769. regError.name_ = methodAnalyzer.GetName();
  770. regError.comment_ = methodAnalyzer.GetDeclaration();
  771. regError.message_ = e.what();
  772. if (regInTemplate)
  773. processedClass.unregisteredTemplateMethods_.push_back(regError);
  774. else
  775. processedClass.unregisteredPersonalMethods_.push_back(regError);
  776. return;
  777. }
  778. string cppClassName = methodAnalyzer.GetClass().GetClassName();
  779. /*MethodRegistration result;
  780. result.name_ = methodAnalyzer.GetName();
  781. result.cppDeclaration_ = ReplaceAll(methodAnalyzer.GetDeclaration(), "\"", "\\\"");*/
  782. Registration result;
  783. result.comment_ = methodAnalyzer.GetDeclaration();
  784. string funcPointer;
  785. string callConv;
  786. //bool templateVersion = true;
  787. if (needWrapper)
  788. {
  789. /*result.glue_ = GenerateWrapper(methodAnalyzer, false, convertedParams, retConv);
  790. result.registration_.funcPointer_ = "AS_FUNCTION_OBJFIRST(" + GenerateWrapperName(methodAnalyzer) + ")";
  791. result.registration_.callConv_ = "AS_CALL_CDECL_OBJFIRST";*/
  792. result.glue_ = GenerateWrapper(methodAnalyzer, regInTemplate, convertedParams, retConv);
  793. funcPointer = "AS_FUNCTION_OBJFIRST(" + GenerateWrapperName(methodAnalyzer, regInTemplate);
  794. if (regInTemplate)
  795. funcPointer += "<" + cppClassName + ">";
  796. funcPointer += ")";
  797. callConv = "AS_CALL_CDECL_OBJFIRST";
  798. }
  799. else
  800. {
  801. /*result.registration_.funcPointer_ = Generate_asMETHODPR(methodAnalyzer, regInTemplate);
  802. result.registration_.callConv_ = "AS_CALL_THISCALL";*/
  803. funcPointer = Generate_asMETHODPR(methodAnalyzer, regInTemplate);
  804. callConv = "AS_CALL_THISCALL";
  805. }
  806. string decl = asReturnType + " " + asFunctionName + "(" + JoinASDeclarations(convertedParams) + ")";
  807. if (methodAnalyzer.IsConst())
  808. decl += " const";
  809. string asClassName = cppClassName;
  810. //result.registration_.asDeclarations_.push_back(decl);
  811. if (regInTemplate)
  812. result.registration_.push_back("engine->RegisterObjectMethod(className, \"" + decl + "\", " + funcPointer + ", " + callConv + ");");
  813. else
  814. result.registration_.push_back("engine->RegisterObjectMethod(\"" + asClassName + "\", \"" + decl + "\", " + funcPointer + ", " + callConv + ");");
  815. // Also register as property if needed
  816. string propertyMark = GetPropertyMark(methodAnalyzer);
  817. if (!propertyMark.empty())
  818. {
  819. if (StartsWith(propertyMark, "BIND_AS_ALIAS_"))
  820. {
  821. asFunctionName = CutStart(propertyMark, "BIND_AS_ALIAS_");
  822. }
  823. else
  824. {
  825. try
  826. {
  827. asFunctionName = CppMethodNameToASProperty(methodAnalyzer);
  828. }
  829. catch (const Exception& e)
  830. {
  831. MemberRegistrationError regError;
  832. regError.name_ = methodAnalyzer.GetName();
  833. regError.comment_ = methodAnalyzer.GetDeclaration();
  834. regError.message_ = e.what();
  835. if (regInTemplate)
  836. processedClass.unregisteredTemplateMethods_.push_back(regError);
  837. else
  838. processedClass.unregisteredPersonalMethods_.push_back(regError);
  839. return;
  840. }
  841. }
  842. decl = asReturnType + " " + asFunctionName + "(" + JoinASDeclarations(convertedParams) + ")";
  843. if (methodAnalyzer.IsConst())
  844. decl += " const";
  845. //result.registration_.asDeclarations_.push_back(decl);
  846. if (regInTemplate)
  847. result.registration_.push_back("engine->RegisterObjectMethod(className, \"" + decl + "\", " + funcPointer + ", " + callConv + ");");
  848. else
  849. result.registration_.push_back("engine->RegisterObjectMethod(\"" + asClassName + "\", \"" + decl + "\", " + funcPointer + ", " + callConv + ");");
  850. //result.registration_.push_back("engine->RegisterObjectMethod(className, \"" + decl + "\", " + funcPointer + ", " + callConv + ");");
  851. }
  852. //processedClass.methods_.push_back(result);
  853. if (regInTemplate)
  854. processedClass.templateMethods_.push_back(result);
  855. else
  856. processedClass.personalMethods_.push_back(result);
  857. }
  858. static void RegisterField(const FieldAnalyzer& fieldAnalyzer, ProcessedClass& processedClass)
  859. {
  860. if (Contains(fieldAnalyzer.GetComment(), "NO_BIND"))
  861. {
  862. MemberRegistrationError regError;
  863. regError.name_ = fieldAnalyzer.GetName();
  864. regError.comment_ = fieldAnalyzer.GetDeclaration();
  865. regError.message_ = "Not registered because have @nobind mark";
  866. processedClass.unregisteredTemplateFields_.push_back(regError);
  867. return;
  868. }
  869. if (Contains(fieldAnalyzer.GetComment(), "MANUAL_BIND"))
  870. {
  871. MemberRegistrationError regError;
  872. regError.name_ = fieldAnalyzer.GetName();
  873. regError.comment_ = fieldAnalyzer.GetDeclaration();
  874. regError.message_ = "Not registered because have @manualbind mark";
  875. processedClass.unregisteredTemplateFields_.push_back(regError);
  876. return;
  877. }
  878. if (fieldAnalyzer.IsStatic())
  879. {
  880. string asType;
  881. try
  882. {
  883. asType = CppTypeToAS(fieldAnalyzer.GetType(), TypeUsage::StaticField);
  884. }
  885. catch (const Exception& e)
  886. {
  887. MemberRegistrationError regError;
  888. regError.name_ = fieldAnalyzer.GetName();
  889. regError.comment_ = fieldAnalyzer.GetDeclaration();
  890. regError.message_ = e.what();
  891. processedClass.unregisteredTemplateStaticFields_.push_back(regError);
  892. return;
  893. }
  894. if (fieldAnalyzer.GetType().IsConst())
  895. asType = "const " + asType;
  896. asType = ReplaceAll(asType, "struct ", "");
  897. string cppClassName = fieldAnalyzer.GetClassName();
  898. string asPropertyName = fieldAnalyzer.GetName();
  899. /*StaticFieldRegistration result;
  900. result.cppDeclaration_ = fieldAnalyzer.GetDeclaration();
  901. result.name_ = fieldAnalyzer.GetName();
  902. result.registration_.asDeclarations_.push_back(asType + " " + asPropertyName);
  903. result.registration_.pointer_ = "(void*)&" + cppClassName + "::" + fieldAnalyzer.GetName();
  904. processedClass.staticFields_.push_back(result);
  905. */
  906. Registration reg;
  907. reg.comment_ = fieldAnalyzer.GetDeclaration();
  908. reg.registration_.push_back(
  909. "engine->SetDefaultNamespace(className);"
  910. "engine->RegisterGlobalProperty(\"" + asType + " " + asPropertyName + "\", " + "(void*)&T::" + fieldAnalyzer.GetName() + ");"
  911. "engine->SetDefaultNamespace(\"\");");
  912. processedClass.templateStaticFields_.push_back(reg);
  913. }
  914. else
  915. {
  916. if (fieldAnalyzer.IsArray())
  917. {
  918. MemberRegistrationError regError;
  919. regError.name_ = fieldAnalyzer.GetName();
  920. regError.comment_ = fieldAnalyzer.GetDeclaration();
  921. regError.message_ = "Not registered because array";
  922. processedClass.unregisteredTemplateFields_.push_back(regError);
  923. return;
  924. }
  925. if (fieldAnalyzer.GetType().IsPointer())
  926. {
  927. MemberRegistrationError regError;
  928. regError.name_ = fieldAnalyzer.GetName();
  929. regError.comment_ = fieldAnalyzer.GetDeclaration();
  930. regError.message_ = "Not registered because pointer";
  931. processedClass.unregisteredTemplateFields_.push_back(regError);
  932. return;
  933. }
  934. string asPropertyType;
  935. try
  936. {
  937. asPropertyType = CppTypeToAS(fieldAnalyzer.GetType(), TypeUsage::Field);
  938. }
  939. catch (const Exception& e)
  940. {
  941. MemberRegistrationError regError;
  942. regError.name_ = fieldAnalyzer.GetName();
  943. regError.comment_ = fieldAnalyzer.GetDeclaration();
  944. regError.message_ = e.what();
  945. processedClass.unregisteredTemplateFields_.push_back(regError);
  946. return;
  947. }
  948. string cppFieldName = fieldAnalyzer.GetName();
  949. assert(!cppFieldName.empty());
  950. string asPropertyName = CutEnd(cppFieldName, "_");
  951. string cppClassName = fieldAnalyzer.GetClassName();
  952. /*FieldRegistration result;
  953. result.name_ = cppFieldName;
  954. result.cppDeclaration_ = fieldAnalyzer.GetDeclaration();
  955. result.registration_.asDeclarations_.push_back(asPropertyType + " " + asPropertyName);
  956. result.registration_.byteOffset_ = "offsetof(" + cppClassName + ", " + cppFieldName + ")";*/
  957. Registration reg;
  958. reg.comment_ = fieldAnalyzer.GetDeclaration();
  959. reg.registration_.push_back("engine->RegisterObjectProperty(className, \"" + asPropertyType + " " + asPropertyName + "\", "
  960. "offsetof(T, " + cppFieldName + "));");
  961. processedClass.templateFields_.push_back(reg);
  962. //processedClass.fields_.push_back(result);
  963. }
  964. }
  965. static void RegisterComparisonOperator(const ClassAnalyzer& classAnalyzer, ProcessedClass& processedClass)
  966. {
  967. string className = classAnalyzer.GetClassName();
  968. shared_ptr<MethodAnalyzer> methodAnalyzer = classAnalyzer.GetMethod("operator<");
  969. assert(methodAnalyzer);
  970. string wrapperName = GenerateWrapperName(*methodAnalyzer);
  971. Registration result;
  972. result.comment_ = methodAnalyzer->GetDeclaration();
  973. result.glue_ =
  974. "template <class T> int " + wrapperName + "(const T& lhs, const T& rhs)\n"
  975. "{\n"
  976. " if (lhs < rhs)\n"
  977. " return -1;\n\n"
  978. " if (lhs > rhs)\n"
  979. " return 1;\n\n"
  980. " return 0;\n"
  981. "}\n";
  982. //result.name_ = methodAnalyzer->GetName();
  983. result.registration_.push_back(
  984. "engine->RegisterObjectMethod(className, \"int opCmp(const " + className + "& in) const\", "
  985. "AS_FUNCTION_OBJFIRST(" + wrapperName + "<T>), AS_CALL_CDECL_OBJFIRST);");
  986. processedClass.templateMethods_.push_back(result);
  987. }
  988. static void TryRegisterImplicitlyDeclaredAssignOperator(const ClassAnalyzer& classAnalyzer, ProcessedClass& processedClass)
  989. {
  990. string className = classAnalyzer.GetClassName();
  991. processedClass.additionalLines_.push_back(" // " + className + "& " + className + "::operator =(const " + className + "&) | Possible implicitly-declared");
  992. processedClass.additionalLines_.push_back(" RegisterImplicitlyDeclaredAssignOperatorIfPossible<" + className + ">(engine, \"" + className + "\");");
  993. }
  994. static void ProcessClass(const ClassAnalyzer& classAnalyzer)
  995. {
  996. if (classAnalyzer.IsInternal())
  997. return;
  998. // TODO: Remove
  999. if (classAnalyzer.IsTemplate())
  1000. return;
  1001. string header = classAnalyzer.GetHeaderFile();
  1002. Result::AddHeader(header);
  1003. if (IsIgnoredHeader(header))
  1004. return;
  1005. ProcessedClass processedClass;
  1006. processedClass.name_ = classAnalyzer.GetClassName();
  1007. processedClass.dirName_ = classAnalyzer.GetDirName();
  1008. processedClass.comment_ = classAnalyzer.GetLocation();
  1009. processedClass.insideDefine_ = InsideDefine(header);
  1010. processedClass.inherianceDeep_ = classAnalyzer.GetInherianceDeep();
  1011. //cout << processedClass.name_ << " DEEP: " << processedClass.inherianceDeep_;
  1012. cout << processedClass.name_ << "\n";
  1013. vector<MethodAnalyzer> methods = classAnalyzer.GetAllPublicMethods();
  1014. for (const MethodAnalyzer& method : methods)
  1015. {
  1016. if (method.IsStatic())
  1017. continue; // TODO remove hack
  1018. if (method.IsThisConstructor())
  1019. RegisterConstructor(method, processedClass);
  1020. else if (method.IsDestructor())
  1021. continue;
  1022. else if (method.IsConstructor())
  1023. continue;
  1024. else
  1025. RegisterMethod(method, processedClass);
  1026. }
  1027. // TODO отдельный класс для статических методов?
  1028. vector<MethodAnalyzer> staticMethods = classAnalyzer.GetThisPublicStaticMethods();
  1029. for (const MethodAnalyzer& staticMethod : staticMethods)
  1030. {
  1031. RegisterMethod(staticMethod, processedClass);
  1032. }
  1033. vector<FieldAnalyzer> fields = classAnalyzer.GetThisPublicFields();
  1034. for (const FieldAnalyzer& field : fields)
  1035. RegisterField(field, processedClass);
  1036. vector<FieldAnalyzer> staticFields = classAnalyzer.GetThisPublicStaticFields();
  1037. for (const FieldAnalyzer& staticField : staticFields)
  1038. RegisterField(staticField, processedClass);
  1039. vector<ClassAnalyzer> baseClasses = classAnalyzer.GetBaseClasses();
  1040. for (const ClassAnalyzer& baseClass : baseClasses)
  1041. processedClass.baseClassNames_.push_back(baseClass.GetClassName());
  1042. //processedClass.hiddenMethods_ = classAnalyzer.GetHiddenMethods();
  1043. /*processedClass.hiddenStaticMethods_ = classAnalyzer.GetHiddenStaticMethods();
  1044. processedClass.hiddenFields_ = classAnalyzer.GetHiddenFields();
  1045. processedClass.hiddenStaticFields_ = classAnalyzer.GetHiddenStaticFields();*/
  1046. bool isNoCount = classAnalyzer.IsNoCount();
  1047. if (classAnalyzer.IsAbstract() && !(classAnalyzer.IsRefCounted() || isNoCount))
  1048. {
  1049. processedClass.objectTypeRegistration_ = "// Not registered because value types can not be abstract";
  1050. processedClass.noBind_ = true;
  1051. Result::classes_.push_back(processedClass);
  1052. return;
  1053. }
  1054. string classComment = classAnalyzer.GetComment();
  1055. if (Contains(classComment, "NO_BIND"))
  1056. {
  1057. processedClass.objectTypeRegistration_ = "// Not registered because have @nobind mark";
  1058. processedClass.noBind_ = true;
  1059. Result::classes_.push_back(processedClass);
  1060. return;
  1061. }
  1062. if (Contains(classComment, "MANUAL_BIND"))
  1063. {
  1064. processedClass.objectTypeRegistration_ = "// Not registered because have @manualbind mark";
  1065. processedClass.noBind_ = true;
  1066. Result::classes_.push_back(processedClass);
  1067. return;
  1068. }
  1069. RegisterObjectType(classAnalyzer, processedClass);
  1070. if (classAnalyzer.IsRefCounted() || isNoCount)
  1071. {
  1072. vector<ClassAnalyzer> baseClasses = classAnalyzer.GetAllBaseClasses();
  1073. for (ClassAnalyzer baseClass : baseClasses)
  1074. {
  1075. if (baseClass.IsRefCounted() || baseClass.IsNoCount())
  1076. {
  1077. string cppBaseClassName = baseClass.GetClassName();
  1078. string asBaseClassName = cppBaseClassName;
  1079. string cppClassName = classAnalyzer.GetClassName();
  1080. string asClassName = classAnalyzer.GetClassName();
  1081. string reg = "RegisterSubclass<" + cppBaseClassName + ", " + cppClassName + ">(engine, \"" + asBaseClassName + "\", \"" + asClassName + "\");";
  1082. processedClass.subclassRegistrations_.push_back(reg);
  1083. }
  1084. }
  1085. }
  1086. // 2 operators is replaced by single function opCmp
  1087. if (classAnalyzer.ContainsMethod("operator>") || classAnalyzer.ContainsMethod("operator<"))
  1088. RegisterComparisonOperator(classAnalyzer, processedClass);
  1089. if (!classAnalyzer.ContainsMethod("operator="))
  1090. TryRegisterImplicitlyDeclaredAssignOperator(classAnalyzer, processedClass);
  1091. if (classAnalyzer.IsAbstract()) // Abstract refcounted type
  1092. {
  1093. Result::classes_.push_back(processedClass);
  1094. return;
  1095. }
  1096. if (!classAnalyzer.HasThisConstructor() && IsConstructorRequired(classAnalyzer))
  1097. {
  1098. shared_ptr<SpecialMethodRegistration> result = make_shared<SpecialMethodRegistration>();
  1099. string cppClassName = classAnalyzer.GetClassName();
  1100. string asClassName = classAnalyzer.GetClassName();
  1101. if (classAnalyzer.IsRefCounted() || isNoCount)
  1102. result->registration_ = "engine->RegisterObjectBehaviour(\"" + asClassName + "\", asBEHAVE_FACTORY, \"" +
  1103. asClassName + "@" + (isNoCount ? "" : "+") + " f()\", asFUNCTION(ASCompatibleFactory<" + cppClassName + ">), AS_CALL_CDECL);";
  1104. else
  1105. result->registration_ = "engine->RegisterObjectBehaviour(\"" + asClassName + "\", asBEHAVE_CONSTRUCT, \"void f()\", asFUNCTION(ASCompatibleConstructor<" + cppClassName + ">), AS_CALL_CDECL_OBJFIRST);";
  1106. result->comment_ = cppClassName + "::" + cppClassName + "() | Implicitly-declared";
  1107. processedClass.defaultConstructor_ = result;
  1108. }
  1109. RegisterDestructor(classAnalyzer, processedClass);
  1110. Result::classes_.push_back(processedClass);
  1111. }
  1112. void ProcessAllClasses()
  1113. {
  1114. InitCachedMemberSignatures();
  1115. for (auto element : SourceData::classesByID_)
  1116. {
  1117. xml_node compounddef = element.second;
  1118. ClassAnalyzer analyzer(compounddef);
  1119. ProcessClass(analyzer);
  1120. }
  1121. }
  1122. } // namespace ASBindingGenerator