ASClassBinder.cpp 49 KB

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