JSBHeaderVisitor.h 13 KB

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