JSBHeaderVisitor.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  2. // Please see LICENSE.md in repository root for license information
  3. // https://github.com/AtomicGameEngine/AtomicGameEngine
  4. #pragma once
  5. #include <Atomic/IO/Log.h>
  6. #include <Atomic/Core/ProcessUtils.h>
  7. using namespace Atomic;
  8. #include "JSBHeader.h"
  9. #include "JSBModule.h"
  10. #include "JSBClass.h"
  11. #include "JSBPackage.h"
  12. #include "JSBFunction.h"
  13. #include "JSBNameVisitor.h"
  14. namespace ToolCore
  15. {
  16. class JSBHeader;
  17. class JSBHeaderVisitor : public SymbolVisitor
  18. {
  19. JSBHeader* header_;
  20. JSBModule* module_;
  21. TranslationUnit* unit_;
  22. Namespace* globalNamespace_;
  23. public:
  24. JSBHeaderVisitor(JSBHeader* header, TranslationUnit *unit, Namespace* globalNamespace) :
  25. header_(header),
  26. unit_(unit),
  27. globalNamespace_(globalNamespace)
  28. {
  29. module_ = header_->GetModule();
  30. accept(globalNamespace_);
  31. }
  32. String getNameString(const Name* name)
  33. {
  34. JSBNameVisitor nvisitor;
  35. return nvisitor(name);
  36. }
  37. JSBType* processTypeConversion(Type* type)
  38. {
  39. JSBType* jtype = NULL;
  40. if (type->isIntegerType())
  41. {
  42. IntegerType* itype = type->asIntegerType();
  43. jtype = new JSBPrimitiveType(itype->kind());
  44. }
  45. else if (type->isFloatType())
  46. {
  47. jtype = new JSBPrimitiveType(JSBPrimitiveType::Float);
  48. }
  49. else if (type->isNamedType())
  50. {
  51. NamedType* ntype = type->asNamedType();
  52. String classname = getNameString(ntype->name());
  53. if (classname.StartsWith("Atomic::"))
  54. classname.Replace("Atomic::", "");
  55. if (classname == "Vector")
  56. {
  57. if (ntype->name()->asTemplateNameId())
  58. {
  59. const TemplateNameId* tnid = ntype->name()->asTemplateNameId();
  60. FullySpecifiedType pfst = tnid->templateArgumentAt(0);
  61. JSBType* vtype = processTypeConversion(pfst.type());
  62. if (vtype)
  63. {
  64. jtype = new JSBVectorType(vtype);
  65. }
  66. }
  67. }
  68. else if (classname == "String")
  69. {
  70. jtype = new JSBStringType();
  71. }
  72. else if (classname == "StringHash")
  73. {
  74. jtype = new JSBStringHashType();
  75. }
  76. else if (classname == "JS_HEAP_PTR")
  77. {
  78. jtype = new JSBHeapPtrType();
  79. }
  80. else
  81. {
  82. JSBClass* jclass = JSBPackage::GetClassAllPackages(classname);
  83. if (jclass)
  84. jtype = new JSBClassType(jclass);
  85. else
  86. {
  87. // this might be an enum
  88. JSBEnum* jenum = JSBPackage::GetEnumAllPackages(classname);
  89. if (jenum)
  90. jtype = new JSBEnumType(jenum);
  91. }
  92. }
  93. }
  94. else if (type->asUndefinedType())
  95. {
  96. UndefinedType* utype = type->asUndefinedType();
  97. //ErrorExit("Undefined type");
  98. }
  99. return jtype;
  100. }
  101. JSBFunctionType* processFunctionType(FullySpecifiedType fst, bool retType = false)
  102. {
  103. JSBType* jtype = NULL;
  104. Type* type = fst.type();
  105. bool isPointer = false;
  106. bool isSharedPtr = false;
  107. bool isReference = false;
  108. bool isTemplate = false;
  109. bool isConst = false;
  110. if (type->isPointerType())
  111. {
  112. isPointer=true;
  113. FullySpecifiedType pfst = type->asPointerType()->elementType();
  114. type = pfst.type();
  115. }
  116. if (type->isReferenceType())
  117. {
  118. isReference=true;
  119. FullySpecifiedType pfst = type->asReferenceType()->elementType();
  120. type = pfst.type();
  121. isConst = pfst.isConst();
  122. }
  123. if (!isPointer && retType)
  124. {
  125. if (type->isNamedType())
  126. {
  127. NamedType* ntype = type->asNamedType();
  128. if (ntype->name()->asTemplateNameId())
  129. {
  130. const TemplateNameId* tnid = ntype->name()->asTemplateNameId();
  131. String classname = getNameString(tnid->identifier()->asNameId());
  132. if (classname == "SharedPtr")
  133. {
  134. FullySpecifiedType pfst = tnid->templateArgumentAt(0);
  135. type = pfst.type();
  136. isTemplate = true;
  137. }
  138. }
  139. }
  140. }
  141. if (fst.isUnsigned())
  142. {
  143. if (type->isUndefinedType())
  144. {
  145. // this happens when just using "unsigned" in code
  146. jtype = new JSBPrimitiveType(JSBPrimitiveType::Int, true);
  147. }
  148. }
  149. if (!jtype)
  150. jtype = processTypeConversion(type);
  151. if (!jtype)
  152. return NULL;
  153. // read only vectors atm
  154. if (!isConst && jtype->asVectorType())
  155. return NULL;
  156. bool skip = false;
  157. // no pointers to prim atm
  158. if (isPointer || isReference)
  159. {
  160. if (jtype->asPrimitiveType())
  161. skip = true;
  162. else if (!retType && !isConst && (jtype->asStringType() || jtype->asStringHashType()))
  163. {
  164. skip = true;
  165. }
  166. if (skip)
  167. return NULL;
  168. }
  169. JSBFunctionType* ftype = new JSBFunctionType(jtype);
  170. ftype->isPointer_ = isPointer;
  171. ftype->isSharedPtr_ = isSharedPtr;
  172. ftype->isReference_ = isReference;
  173. ftype->isTemplate_ = isTemplate;
  174. ftype->isConst_ = isConst;
  175. return ftype;
  176. }
  177. JSBFunctionType* processFunctionArgType(Argument* arg)
  178. {
  179. JSBFunctionType* jtype = processFunctionType(arg->type());
  180. if (!jtype)
  181. return NULL;
  182. jtype->name_ = getNameString(arg->name());
  183. return jtype;
  184. }
  185. JSBFunctionType* processFunctionReturnType(Function* function)
  186. {
  187. if (!function->hasReturnType())
  188. {
  189. return NULL;
  190. }
  191. JSBFunctionType* jtype = processFunctionType(function->returnType(), true);
  192. if (!jtype)
  193. return NULL;
  194. return jtype;
  195. }
  196. JSBFunction* processFunction(JSBClass* klass, Function* function)
  197. {
  198. JSBFunction* jfunction = new JSBFunction(klass);
  199. // don't ... atm
  200. if (function->isVariadic())
  201. return NULL;
  202. String name = getNameString(function->name());
  203. jfunction->SetName(name);
  204. // don't support operators atm
  205. if (name.StartsWith("operator "))
  206. return NULL;
  207. if (name == klass->GetNativeName())
  208. jfunction->SetConstructor();
  209. if (name.StartsWith("~"))
  210. jfunction->SetDestructor();
  211. if (function->isOverride())
  212. jfunction->SetVirtual(true);
  213. // see if we support return type
  214. if (function->hasReturnType() && !function->returnType().type()->isVoidType())
  215. {
  216. JSBFunctionType* returnType = processFunctionReturnType(function);
  217. if (!returnType)
  218. return NULL;
  219. jfunction->SetReturnType(returnType);
  220. }
  221. if (function->hasArguments())
  222. {
  223. for (unsigned i = 0; i < function->argumentCount(); i++)
  224. {
  225. Symbol* symbol = function->argumentAt(i);
  226. if (symbol->isArgument())
  227. {
  228. Argument* arg = symbol->asArgument();
  229. JSBFunctionType* ftype = processFunctionArgType(arg);
  230. if (!ftype)
  231. return NULL;
  232. if (arg->hasInitializer())
  233. {
  234. ftype->initializer_ = arg->initializer()->chars();
  235. if (ftype->initializer_.StartsWith("\\"))
  236. ftype->initializer_ = "\"" + ftype->initializer_ + "\"";
  237. }
  238. jfunction->AddParameter(ftype);
  239. }
  240. else
  241. {
  242. return NULL;
  243. }
  244. }
  245. }
  246. jfunction->sourceLocation_ = function->sourceLocation();
  247. jfunction->fileName_ = function->fileName();
  248. jfunction->sourceLine_ = function->line();
  249. jfunction->sourceColumn_ = function->column();
  250. //const Token &token = unit_->tokenAt(function->sourceLocation());
  251. //const char* source = unit_->firstSourceChar() + token.byteOffset;
  252. const char* comment = NULL;
  253. for (unsigned i = 0; i < unit_->commentCount(); i++)
  254. {
  255. const Token &tcomment = unit_->commentAt(i);
  256. unsigned line;
  257. unit_->getPosition(tcomment.utf16charOffset, &line);
  258. if (line == function->line() - 1)
  259. {
  260. comment = unit_->firstSourceChar() + tcomment.byteOffset;
  261. break;
  262. }
  263. }
  264. if (comment && strlen(comment) > 3)
  265. {
  266. if (comment[0] == '/' && comment[1] == '/' && comment[2] == '/')
  267. {
  268. int index = 3;
  269. while(comment[index] && comment[index] != '\n' && comment[index] != '\r')
  270. {
  271. String docString = jfunction->GetDocString();
  272. docString += comment[index++];
  273. jfunction->SetDocString(docString);
  274. }
  275. }
  276. }
  277. return jfunction;
  278. }
  279. virtual bool visit(Namespace *nspace)
  280. {
  281. String name = getNameString(nspace->name());
  282. // LOGINFOF("Namespace: %s", name.CString());
  283. return true;
  284. }
  285. // reject template types
  286. virtual bool visit(Template *t)
  287. {
  288. return false;
  289. }
  290. // enums visited in preprocessor visitor
  291. virtual bool visit(Enum *penum)
  292. {
  293. return false;
  294. }
  295. // global var decl or function
  296. virtual bool visit(Declaration* decl)
  297. {
  298. if (decl->isTypedef())
  299. return true;
  300. FullySpecifiedType dtype = decl->type();
  301. Type* type = dtype.type();
  302. if (type->isPointerType() || type->isReferenceType())
  303. return true;
  304. if (type->asEnumType())
  305. return true;
  306. bool _unsigned = false;
  307. if (dtype.isUnsigned())
  308. _unsigned = true;
  309. if (!type->asFloatType() && !type->asIntegerType() && !_unsigned)
  310. {
  311. return true;
  312. }
  313. module_->RegisterConstant(getNameString(decl->name()).CString());
  314. return true;
  315. }
  316. virtual bool visit(Class *klass)
  317. {
  318. String name = getNameString(klass->name());
  319. JSBClass* jclass = module_->GetClass(name);
  320. if (!jclass)
  321. {
  322. return false;
  323. }
  324. jclass->SetHeader(header_);
  325. for (unsigned i = 0; i < klass->baseClassCount(); i++)
  326. {
  327. BaseClass* baseclass = klass->baseClassAt(i);
  328. String baseclassname = getNameString(baseclass->name());
  329. JSBClass* base = JSBPackage::GetClassAllPackages(baseclassname);
  330. if (!base)
  331. {
  332. LOGINFOF("Warning: %s baseclass %s not in bindings", name.CString(), baseclassname.CString());
  333. }
  334. else
  335. {
  336. jclass->SetBaseClass(base);
  337. }
  338. }
  339. for (unsigned i = 0; i < klass->memberCount(); i++)
  340. {
  341. Symbol* symbol = klass->memberAt(i);
  342. Declaration* decl = symbol->asDeclaration();
  343. // if the function describes the body in the header
  344. Function* function = symbol->asFunction();
  345. // otherwise it could be a decl
  346. if (!function && decl)
  347. function = decl->type()->asFunctionType();
  348. if (function)
  349. {
  350. if (function->isPureVirtual())
  351. jclass->SetAbstract();
  352. // only want public functions
  353. if (!symbol->isPublic())
  354. continue;
  355. JSBFunction* jfunction = processFunction(jclass, function);
  356. if (jfunction)
  357. jclass->AddFunction(jfunction);
  358. }
  359. }
  360. // return false so we don't traverse the class members
  361. return false;
  362. }
  363. };
  364. }