ASClassBinder.cpp 49 KB

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