JSBHeaderVisitor.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. //
  2. // Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #pragma once
  23. #include <Atomic/IO/Log.h>
  24. #include <Atomic/Core/ProcessUtils.h>
  25. using namespace Atomic;
  26. #include "JSBHeader.h"
  27. #include "JSBModule.h"
  28. #include "JSBClass.h"
  29. #include "JSBPackage.h"
  30. #include "JSBFunction.h"
  31. #include "JSBNameVisitor.h"
  32. namespace ToolCore
  33. {
  34. class JSBHeader;
  35. class JSBPrimitiveType;
  36. class JSBHeaderVisitor : public SymbolVisitor
  37. {
  38. JSBHeader* header_;
  39. JSBModule* module_;
  40. TranslationUnit* unit_;
  41. Namespace* globalNamespace_;
  42. public:
  43. JSBHeaderVisitor(JSBHeader* header, TranslationUnit *unit, Namespace* globalNamespace) :
  44. header_(header),
  45. unit_(unit),
  46. globalNamespace_(globalNamespace)
  47. {
  48. module_ = header_->GetModule();
  49. accept(globalNamespace_);
  50. }
  51. String getNameString(const Name* name)
  52. {
  53. JSBNameVisitor nvisitor;
  54. return nvisitor(name);
  55. }
  56. JSBType* processTypeConversion(Type* type, FullySpecifiedType fst)
  57. {
  58. JSBType* jtype = NULL;
  59. if (type->isIntegerType())
  60. {
  61. IntegerType* itype = type->asIntegerType();
  62. jtype = new JSBPrimitiveType(itype->kind());
  63. }
  64. else if (type->isFloatType())
  65. {
  66. jtype = new JSBPrimitiveType(JSBPrimitiveType::Float);
  67. }
  68. else if (type->isNamedType())
  69. {
  70. NamedType* ntype = type->asNamedType();
  71. String classname = getNameString(ntype->name());
  72. if (classname.StartsWith("Atomic::"))
  73. classname.Replace("Atomic::", "");
  74. if (classname == "VariantVector")
  75. {
  76. JSBClass* jclass = JSBPackage::GetClassAllPackages("ScriptVariant");
  77. assert(jclass);
  78. jtype = new JSBVectorType(new JSBClassType(jclass), false, true);
  79. }
  80. else if (classname == "Vector" || classname == "PODVector")
  81. {
  82. PODVector<TemplateType> types;
  83. unwrapTemplateType(fst, types);
  84. if (types.Size() == 2)
  85. {
  86. JSBType* vtype = processTypeConversion((Type*) types[1].type_, types[1].fstype_);
  87. if (vtype)
  88. {
  89. jtype = new JSBVectorType(vtype, classname == "PODVector");
  90. }
  91. }
  92. else if (types.Size() == 3 && ( getNameString(types[1].name_) == "SharedPtr" || getNameString(types[1].name_) == "WeakPtr"))
  93. {
  94. JSBType* vtype = processTypeConversion((Type*) types[2].type_, types[2].fstype_);
  95. if (vtype)
  96. {
  97. JSBVectorType* jvtype = new JSBVectorType(vtype, classname == "PODVector");
  98. if (getNameString(types[1].name_) == "SharedPtr")
  99. {
  100. jvtype->vectorTypeIsSharedPtr_ = true;
  101. }
  102. else if (getNameString(types[1].name_) == "WeakPtr")
  103. {
  104. jvtype->vectorTypeIsWeakPtr_ = true;
  105. }
  106. jtype = jvtype;
  107. }
  108. }
  109. }
  110. else if (classname == "String")
  111. {
  112. jtype = new JSBStringType();
  113. }
  114. else if (classname == "StringHash")
  115. {
  116. jtype = new JSBStringHashType();
  117. }
  118. else if (classname == "JS_HEAP_PTR")
  119. {
  120. jtype = new JSBHeapPtrType();
  121. }
  122. else
  123. {
  124. JSBClass* jclass = JSBPackage::GetClassAllPackages(classname, true);
  125. if (jclass)
  126. jtype = new JSBClassType(jclass);
  127. else
  128. {
  129. // this might be an enum
  130. JSBEnum* jenum = JSBPackage::GetEnumAllPackages(classname);
  131. if (jenum)
  132. jtype = new JSBEnumType(jenum);
  133. }
  134. }
  135. }
  136. else if (type->asUndefinedType())
  137. {
  138. UndefinedType* utype = type->asUndefinedType();
  139. //ErrorExit("Undefined type");
  140. }
  141. return jtype;
  142. }
  143. struct TemplateType
  144. {
  145. FullySpecifiedType fstype_;
  146. bool isPointer_;
  147. bool isReference_;
  148. const Name* name_;
  149. const Type* type_;
  150. static void Init(TemplateType& ttype)
  151. {
  152. ttype.isPointer_ = false;
  153. ttype.isReference_ = false;
  154. ttype.name_ = 0;
  155. ttype.type_ = 0;
  156. }
  157. };
  158. bool unwrapTemplateType(const FullySpecifiedType& fstype, PODVector<TemplateType>& types)
  159. {
  160. TemplateType ttype;
  161. TemplateType::Init(ttype);
  162. ttype.fstype_ = fstype;
  163. ttype.type_ = fstype.type();
  164. if (ttype.type_->isPointerType())
  165. {
  166. ttype.isPointer_=true;
  167. FullySpecifiedType pfst = ttype.type_->asPointerType()->elementType();
  168. ttype.type_ = pfst.type();
  169. }
  170. if (ttype.type_->isReferenceType())
  171. {
  172. ttype.isReference_=true;
  173. FullySpecifiedType pfst = ttype.type_->asReferenceType()->elementType();
  174. ttype.type_ = pfst.type();
  175. }
  176. const NamedType* ntype = ttype.type_->asNamedType();
  177. if (!ntype)
  178. return false;
  179. if (ntype->name()->asTemplateNameId())
  180. {
  181. const TemplateNameId* tnid = ntype->name()->asTemplateNameId();
  182. ttype.name_ = tnid->identifier()->asNameId();
  183. types.Push(ttype);
  184. unwrapTemplateType(tnid->templateArgumentAt(0), types);
  185. return true;
  186. }
  187. ttype.name_ = ntype->name();
  188. types.Push(ttype);
  189. return false;
  190. }
  191. JSBFunctionType* processFunctionType(FullySpecifiedType fst, bool retType = false)
  192. {
  193. JSBType* jtype = NULL;
  194. Type* type = fst.type();
  195. bool isPointer = false;
  196. bool isSharedPtr = false;
  197. bool isReference = false;
  198. bool isTemplate = false;
  199. bool isConst = false;
  200. if (type->isPointerType())
  201. {
  202. isPointer=true;
  203. FullySpecifiedType pfst = type->asPointerType()->elementType();
  204. type = pfst.type();
  205. }
  206. if (type->isReferenceType())
  207. {
  208. isReference=true;
  209. FullySpecifiedType pfst = type->asReferenceType()->elementType();
  210. type = pfst.type();
  211. isConst = pfst.isConst();
  212. }
  213. if (!isPointer && retType)
  214. {
  215. if (type->isNamedType())
  216. {
  217. NamedType* ntype = type->asNamedType();
  218. if (ntype->name()->asTemplateNameId())
  219. {
  220. PODVector<TemplateType> types;
  221. unwrapTemplateType(fst, types);
  222. String classname = getNameString(types[0].name_);
  223. // SharedPtr
  224. if ( classname == "SharedPtr" && types.Size() == 2 )
  225. {
  226. type = (Type*) types[1].type_;
  227. isTemplate = true;
  228. isSharedPtr = true;
  229. }
  230. }
  231. }
  232. }
  233. if (fst.isUnsigned())
  234. {
  235. if (type->isUndefinedType())
  236. {
  237. // this happens when just using "unsigned" in code
  238. jtype = new JSBPrimitiveType(JSBPrimitiveType::Int, true);
  239. }
  240. }
  241. if (!jtype)
  242. {
  243. jtype = processTypeConversion(type, fst);
  244. // explicit script string -> StringHash required
  245. if (jtype && jtype->asStringHashType())
  246. isReference = false;
  247. if (fst.isUnsigned() && jtype->asPrimitiveType())
  248. jtype->asPrimitiveType()->isUnsigned_ = true;
  249. }
  250. if (!jtype)
  251. return NULL;
  252. bool skip = false;
  253. // no pointers to prim atm
  254. if (isPointer || isReference)
  255. {
  256. if (jtype->asPrimitiveType())
  257. skip = true;
  258. else if (!retType && !isConst && (jtype->asStringType() || jtype->asStringHashType()))
  259. {
  260. skip = true;
  261. }
  262. if (skip)
  263. return NULL;
  264. }
  265. // We don't support pointers to Vector2/Vector3/etc which are generally out values
  266. if (isPointer && jtype->asClassType() && jtype->asClassType()->class_->IsNumberArray())
  267. return NULL;
  268. JSBFunctionType* ftype = new JSBFunctionType(jtype);
  269. ftype->isPointer_ = isPointer;
  270. ftype->isSharedPtr_ = isSharedPtr;
  271. ftype->isReference_ = isReference;
  272. ftype->isTemplate_ = isTemplate;
  273. ftype->isConst_ = isConst;
  274. return ftype;
  275. }
  276. JSBFunctionType* processFunctionArgType(Argument* arg)
  277. {
  278. JSBFunctionType* jtype = processFunctionType(arg->type());
  279. if (!jtype)
  280. return NULL;
  281. jtype->name_ = getNameString(arg->name());
  282. return jtype;
  283. }
  284. JSBFunctionType* processFunctionReturnType(Function* function)
  285. {
  286. if (!function->hasReturnType())
  287. {
  288. return NULL;
  289. }
  290. JSBFunctionType* jtype = processFunctionType(function->returnType(), true);
  291. if (!jtype)
  292. return NULL;
  293. return jtype;
  294. }
  295. String parseDocString(int commentLine) const
  296. {
  297. const char* comment = NULL;
  298. for (unsigned i = 0; i < unit_->commentCount(); i++)
  299. {
  300. const Token &tcomment = unit_->commentAt(i);
  301. unsigned line;
  302. unit_->getPosition(tcomment.utf16charsEnd(), &line);
  303. if (line == commentLine)
  304. {
  305. comment = unit_->firstSourceChar() + tcomment.byteOffset;
  306. break;
  307. }
  308. }
  309. String docString;
  310. if (comment && strlen(comment) > 3)
  311. {
  312. if (comment[0] == '/' && comment[1] == '/' && comment[2] == '/')
  313. {
  314. int index = 3;
  315. while(comment[index] && comment[index] != '\n' && comment[index] != '\r')
  316. {
  317. docString += comment[index++];
  318. }
  319. }
  320. if (comment[0] == '/' && comment[1] == '*' && comment[2] == '*')
  321. {
  322. int index = 3;
  323. bool foundStar = false;
  324. while(comment[index])
  325. {
  326. // did we find a star in the last loop?
  327. if (foundStar)
  328. {
  329. // We have a an end of block indicator, let's break
  330. if (comment[index] == '/' && foundStar)
  331. break;
  332. // This is just a star in the comment, not an end of comment indicator. Let's keep it
  333. docString += '*';
  334. }
  335. foundStar = comment[index] == '*';
  336. if (!foundStar)
  337. docString += comment[index];
  338. index++;
  339. }
  340. }
  341. }
  342. return docString;
  343. }
  344. JSBFunction* processFunction(JSBClass* klass, Function* function)
  345. {
  346. JSBFunction* jfunction = new JSBFunction(klass);
  347. // don't ... atm
  348. if (function->isVariadic())
  349. return NULL;
  350. String name = getNameString(function->name());
  351. jfunction->SetName(name);
  352. // don't support operators atm
  353. if (name.StartsWith("operator "))
  354. return NULL;
  355. if (name == klass->GetNativeName())
  356. jfunction->SetConstructor();
  357. if (name.StartsWith("~"))
  358. jfunction->SetDestructor();
  359. if (function->isVirtual())
  360. jfunction->SetVirtual(true);
  361. if (function->isStatic())
  362. jfunction->SetStatic(true);
  363. // see if we support return type
  364. if (function->hasReturnType() && !function->returnType().type()->isVoidType())
  365. {
  366. JSBFunctionType* returnType = processFunctionReturnType(function);
  367. if (!returnType)
  368. return NULL;
  369. jfunction->SetReturnType(returnType);
  370. }
  371. if (function->hasArguments())
  372. {
  373. for (unsigned i = 0; i < function->argumentCount(); i++)
  374. {
  375. Symbol* symbol = function->argumentAt(i);
  376. if (symbol->isArgument())
  377. {
  378. Argument* arg = symbol->asArgument();
  379. JSBFunctionType* ftype = processFunctionArgType(arg);
  380. // TODO: expose interfaces to TS
  381. if (ftype && ftype->type_->asClassType() && ftype->type_->asClassType()->class_->IsInterface())
  382. {
  383. jfunction->SetSkipLanguage(BINDINGLANGUAGE_JAVASCRIPT);
  384. }
  385. if (!ftype)
  386. {
  387. // if we don't have an initializer, the function cannot be bound
  388. // as unscriptable type
  389. if (!arg->hasInitializer())
  390. return NULL;
  391. // otherwise, break and the optional args will be ignored
  392. break;
  393. }
  394. if (arg->hasInitializer())
  395. {
  396. ftype->initializer_ = arg->initializer()->chars();
  397. if (arg->initializer()->_quotedString)
  398. ftype->initializer_ = "\"" + ftype->initializer_ + "\"";
  399. }
  400. jfunction->AddParameter(ftype);
  401. }
  402. else
  403. {
  404. return NULL;
  405. }
  406. }
  407. }
  408. jfunction->sourceLocation_ = function->sourceLocation();
  409. jfunction->fileName_ = function->fileName();
  410. jfunction->sourceLine_ = function->line();
  411. jfunction->sourceColumn_ = function->column();
  412. //const Token &token = unit_->tokenAt(function->sourceLocation());
  413. //const char* source = unit_->firstSourceChar() + token.byteOffset;
  414. String docString = parseDocString(function->line() - 1);
  415. if (docString.Length())
  416. jfunction->SetDocString(docString);
  417. return jfunction;
  418. }
  419. virtual bool visit(Namespace *nspace)
  420. {
  421. String name = getNameString(nspace->name());
  422. // LOGINFOF("Namespace: %s", name.CString());
  423. return true;
  424. }
  425. // reject template types
  426. virtual bool visit(Template *t)
  427. {
  428. return false;
  429. }
  430. // enums visited in preprocessor visitor
  431. virtual bool visit(Enum *penum)
  432. {
  433. return false;
  434. }
  435. // global var decl or function
  436. virtual bool visit(Declaration* decl)
  437. {
  438. if (decl->isTypedef())
  439. return true;
  440. FullySpecifiedType dtype = decl->type();
  441. Type* type = dtype.type();
  442. if (type->isNamedType())
  443. {
  444. String classname = getNameString(type->asNamedType()->name());
  445. if ( dtype.isConst() && classname == "String" ) // find a const string
  446. {
  447. const StringLiteral* sinit = decl->getInitializer();
  448. if (sinit)
  449. {
  450. if (sinit->chars())
  451. {
  452. String svalue = sinit->chars();
  453. module_->RegisterConstant(getNameString(decl->name()).CString(), svalue, JSBPrimitiveType::Char );
  454. return true; // tag this constant as a Char type, because there is no String Primitive type
  455. }
  456. }
  457. }
  458. }
  459. if (type->isPointerType() || type->isReferenceType())
  460. return true;
  461. if (type->asEnumType())
  462. return true;
  463. bool _unsigned = false;
  464. if (dtype.isUnsigned())
  465. _unsigned = true;
  466. if (!type->asFloatType() && !type->asIntegerType() && !_unsigned)
  467. {
  468. return true;
  469. }
  470. String value;
  471. const StringLiteral* init = decl->getInitializer();
  472. if (init)
  473. {
  474. if (init->chars())
  475. value = init->chars();
  476. }
  477. if (dtype.isConst())
  478. {
  479. if (type->isIntegerType() || _unsigned)
  480. {
  481. module_->RegisterConstant(getNameString(decl->name()).CString(), value, JSBPrimitiveType::Int, _unsigned);
  482. }
  483. else
  484. {
  485. module_->RegisterConstant(getNameString(decl->name()).CString(), value, JSBPrimitiveType::Float);
  486. }
  487. }
  488. return true;
  489. }
  490. virtual bool visit(Class *klass)
  491. {
  492. String name = getNameString(klass->name());
  493. JSBClass* jclass = module_->GetClass(name, true);
  494. if (!jclass)
  495. {
  496. return false;
  497. }
  498. jclass->SetHeader(header_);
  499. String docString = parseDocString(klass->line() - 1);
  500. if (docString.Length())
  501. jclass->SetDocString(docString);
  502. for (unsigned i = 0; i < klass->baseClassCount(); i++)
  503. {
  504. BaseClass* baseclass = klass->baseClassAt(i);
  505. String baseclassname = getNameString(baseclass->name());
  506. JSBClass* base = JSBPackage::GetClassAllPackages(baseclassname);
  507. if (!base)
  508. {
  509. JSBClass* interface = JSBPackage::GetClassAllPackages(baseclassname, true);
  510. if (interface)
  511. {
  512. jclass->AddInterface(interface);
  513. }
  514. else
  515. {
  516. if (!i)
  517. {
  518. ATOMIC_LOGINFOF("Warning: %s first baseclass %s not in bindings", name.CString(), baseclassname.CString());
  519. }
  520. }
  521. }
  522. else
  523. {
  524. jclass->SetBaseClass(base);
  525. }
  526. }
  527. for (unsigned i = 0; i < klass->memberCount(); i++)
  528. {
  529. Symbol* symbol = klass->memberAt(i);
  530. Declaration* decl = symbol->asDeclaration();
  531. // if the function describes the body in the header
  532. Function* function = symbol->asFunction();
  533. // otherwise it could be a decl
  534. if (!function && decl)
  535. function = decl->type()->asFunctionType();
  536. if (function)
  537. {
  538. if (function->isPureVirtual())
  539. jclass->SetAbstract();
  540. // only want public functions
  541. if (!symbol->isPublic())
  542. continue;
  543. JSBFunction* jfunction = processFunction(jclass, function);
  544. if (jfunction)
  545. jclass->AddFunction(jfunction);
  546. }
  547. }
  548. // return false so we don't traverse the class members
  549. return false;
  550. }
  551. };
  552. }