ASClassBinder.cpp 49 KB

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