BfDefBuilder.cpp 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091
  1. #include "BeefySysLib/util/AllocDebug.h"
  2. #include "BfDefBuilder.h"
  3. #include "BeefySysLib/util/Hash.h"
  4. #include "BfParser.h"
  5. #include "BfResolvePass.h"
  6. #include "BeefySysLib/util/PerfTimer.h"
  7. #include "BeefySysLib/util/BeefPerf.h"
  8. #include "BfUtil.h"
  9. USING_NS_BF;
  10. static void HashNode(HashContext& ctx, BfAstNode* astNode)
  11. {
  12. // Add a separator marker so two nodes hashed back-to-back won't mix
  13. uint8 marker = 0;
  14. ctx.Mixin(&marker, 1);
  15. if (astNode == NULL)
  16. return;
  17. ctx.Mixin(astNode->GetSourceData()->mSrc + astNode->GetSrcStart(), astNode->GetSrcLength());
  18. }
  19. static void HashNode(HashContext& ctx, BfAstNode* astNode, BfAstNode* endNode)
  20. {
  21. // Add a separator marker so two nodes hashed back-to-back won't mix
  22. uint8 marker = 0;
  23. ctx.Mixin(&marker, 1);
  24. if (endNode == NULL)
  25. {
  26. HashNode(ctx, astNode);
  27. return;
  28. }
  29. ctx.Mixin(astNode->GetSourceData()->mSrc + astNode->GetSrcStart(), endNode->GetSrcStart() - astNode->GetSrcStart());
  30. }
  31. static Val128 HashNode(BfAstNode* astNode)
  32. {
  33. if (astNode == NULL)
  34. return Val128();
  35. return Hash128(astNode->GetSourceData()->mSrc + astNode->GetSrcStart(), astNode->GetSrcLength());
  36. }
  37. static Val128 HashNode(BfAstNode* astNode, BfAstNode* endNode)
  38. {
  39. if (endNode == NULL)
  40. return HashNode(astNode);
  41. return Hash128(astNode->GetSourceData()->mSrc + astNode->GetSrcStart(), endNode->GetSrcStart() - astNode->GetSrcStart());
  42. }
  43. static Val128 HashString(const StringImpl& str, const Val128& seed = Val128())
  44. {
  45. return Hash128(str.c_str(), (int)str.length(), seed);
  46. }
  47. BfDefBuilder::BfDefBuilder(BfSystem* bfSystem)
  48. {
  49. mPassInstance = NULL;
  50. mSystem = bfSystem;
  51. mCurTypeDef = NULL;
  52. mCurActualTypeDef = NULL;
  53. mFullRefresh = false;
  54. mResolvePassData = NULL;
  55. mCurSource = NULL;
  56. mFullHashCtx = NULL;
  57. mSignatureHashCtx = NULL;
  58. }
  59. BfDefBuilder::~BfDefBuilder()
  60. {
  61. for (auto& usingNamespace : mNamespaceSearch)
  62. mSystem->ReleaseAtomComposite(usingNamespace);
  63. }
  64. void BfDefBuilder::Process(BfPassInstance* passInstance, BfSource* bfSource, bool fullRefresh)
  65. {
  66. String fileName;
  67. BfParser* parser = bfSource->ToParser();
  68. if (parser != NULL)
  69. fileName = parser->mFileName;
  70. BP_ZONE_F("BfDefBuilder::Process %s", fileName.c_str());
  71. BfLogSys(parser->mSystem, "DefBuilder::Process parser %p\n", parser);
  72. if (mResolvePassData == NULL)
  73. mSystem->mNeedsTypesHandledByCompiler = true;
  74. mPassInstance = passInstance;
  75. /*if (parser->mCursorIdx == -1)
  76. {
  77. //gDefBuilderPerfManager.StartRecording();
  78. }*/
  79. bool isAutocomplete = false;
  80. if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
  81. {
  82. mCurSource = bfSource;
  83. Visit(bfSource->mRootNode);
  84. mCurSource = NULL;
  85. mPassInstance = NULL;
  86. return;
  87. }
  88. mFullRefresh = fullRefresh;
  89. // for (auto typeDef : mSystem->mTypeDefs)
  90. // {
  91. // if ((!typeDef->mIsCombinedPartial) && (typeDef->GetLastSource() == bfSource->mPrevRevision))
  92. // typeDef->mDefState = BfTypeDef::DefState_AwaitingNewVersion;
  93. // }
  94. if (bfSource->mPrevRevision != NULL)
  95. {
  96. for (auto typeDef : bfSource->mPrevRevision->mTypeDefs)
  97. {
  98. BF_ASSERT((typeDef->mDefState >= BfTypeDef::DefState_New) && (typeDef->mDefState < BfTypeDef::DefState_Deleted));
  99. typeDef->mDefState = BfTypeDef::DefState_AwaitingNewVersion;
  100. }
  101. }
  102. {
  103. BP_ZONE("RootNode");
  104. if (bfSource->mRootNode != NULL)
  105. {
  106. mCurSource = bfSource;
  107. Visit(bfSource->mRootNode);
  108. mCurSource = NULL;
  109. }
  110. }
  111. if (bfSource->mPrevRevision != NULL)
  112. {
  113. for (auto typeDef : bfSource->mPrevRevision->mTypeDefs)
  114. {
  115. if (!typeDef->mIsCombinedPartial)
  116. {
  117. if (typeDef->mDefState == BfTypeDef::DefState_AwaitingNewVersion)
  118. {
  119. BfLogSys(parser->mSystem, "DefBuilder::Process deleting typeDef %p\n", typeDef);
  120. typeDef->mName->mAtomUpdateIdx = ++mSystem->mAtomUpdateIdx;
  121. typeDef->mDefState = BfTypeDef::DefState_Deleted;
  122. mSystem->mTypeMapVersion++;
  123. }
  124. }
  125. }
  126. }
  127. mPassInstance = NULL;
  128. }
  129. void BfDefBuilder::Visit(BfIdentifierNode* identifier)
  130. {
  131. if (mResolvePassData != NULL)
  132. mResolvePassData->mExteriorAutocompleteCheckNodes.push_back(identifier);
  133. }
  134. // We need to be aware of the startNode because the reducer adds specifiers like 'static' and 'public' AFTER the method has
  135. // already been handled, so we need to ignore that space while determining if we're "inside" this method or not during
  136. // autocompletion
  137. bool BfDefBuilder::WantsNode(BfAstNode* wholeNode, BfAstNode* startNode, int addLen)
  138. {
  139. if ((mResolvePassData == NULL) || (mResolvePassData->mParser->mCursorIdx == -1))
  140. return true;
  141. // We need to get all nodes when we get fixits because the cursor could be either before or after fields with
  142. // warnings, but still on the correct line
  143. //if (mResolvePassData->mResolveType == BfResolveType_GetFixits)
  144. //return true;
  145. addLen++;
  146. if ((mResolvePassData->mParser->mCursorIdx >= wholeNode->GetSrcStart()) && (mResolvePassData->mParser->mCursorIdx < wholeNode->GetSrcEnd() + addLen))
  147. {
  148. if ((startNode == NULL) || (mResolvePassData->mParser->mCursorIdx >= startNode->GetSrcStart()))
  149. return true;
  150. }
  151. return false;
  152. }
  153. static int sGenericParamIdx = 0;
  154. void BfDefBuilder::ParseGenericParams(BfGenericParamsDeclaration* genericParamsDecl, BfGenericConstraintsDeclaration* genericConstraints, Array<BfGenericParamDef*>& genericParams, int outerGenericSize)
  155. {
  156. if (genericParamsDecl != NULL)
  157. {
  158. int startIdx = (int)genericParams.size();
  159. for (int genericParamIdx = 0; genericParamIdx < (int)genericParamsDecl->mGenericParams.size(); genericParamIdx++)
  160. {
  161. BfIdentifierNode* genericParamNode = genericParamsDecl->mGenericParams[genericParamIdx];
  162. String name = genericParamNode->ToString();
  163. for (int checkParamsIdx = startIdx; checkParamsIdx < (int)genericParams.size(); checkParamsIdx++)
  164. {
  165. if (genericParams[checkParamsIdx]->mName == name)
  166. {
  167. mPassInstance->Fail("Duplicate generic param name", genericParamNode);
  168. }
  169. }
  170. auto checkTypeDef = mCurTypeDef;
  171. while (checkTypeDef != NULL)
  172. {
  173. if (&genericParams != &checkTypeDef->mGenericParamDefs)
  174. {
  175. for (int checkParamsIdx = 0; checkParamsIdx < (int)checkTypeDef->mGenericParamDefs.size(); checkParamsIdx++)
  176. {
  177. if (checkTypeDef->mGenericParamDefs[checkParamsIdx]->mName == name)
  178. {
  179. mPassInstance->Warn(0, "Generic param name has same name as generic param from outer type", genericParamNode);
  180. }
  181. }
  182. }
  183. checkTypeDef = checkTypeDef->mOuterType;
  184. }
  185. auto genericParamDef = new BfGenericParamDef();
  186. //genericParamDef->mOwner = mCurActualTypeDef;
  187. genericParamDef->mName = name;
  188. genericParamDef->mNameNodes.Add(genericParamNode);
  189. genericParamDef->mGenericParamFlags = BfGenericParamFlag_None;
  190. genericParams.push_back(genericParamDef);
  191. }
  192. }
  193. if (genericConstraints == NULL)
  194. return;
  195. for (BfGenericConstraint* genericConstraint : genericConstraints->mGenericConstraints)
  196. {
  197. if (genericConstraint->mGenericParamName == NULL)
  198. continue;
  199. String findName = genericConstraint->mGenericParamName->ToString();
  200. BfGenericParamDef* genericParamDef = NULL;
  201. for (int genericParamIdx = outerGenericSize; genericParamIdx < (int) genericParams.size(); genericParamIdx++)
  202. {
  203. auto checkGenericParam = genericParams[genericParamIdx];
  204. if (checkGenericParam->mName == findName)
  205. genericParamDef = checkGenericParam;
  206. }
  207. if (genericParamDef == NULL)
  208. {
  209. mPassInstance->Fail("Cannot find generic parameter in constraint", genericConstraint->mGenericParamName);
  210. if (genericParams.IsEmpty())
  211. continue;
  212. genericParamDef = genericParams[0];
  213. }
  214. else
  215. genericParamDef->mNameNodes.Add(genericConstraint->mGenericParamName);
  216. for (BfAstNode* constraintNode : genericConstraint->mConstraintTypes)
  217. {
  218. String name;
  219. if ((constraintNode->IsA<BfNamedTypeReference>()) || (constraintNode->IsA<BfTokenNode>()))
  220. {
  221. name = constraintNode->ToString();
  222. }
  223. else if (auto tokenPairNode = BfNodeDynCast<BfTokenPairNode>(constraintNode))
  224. {
  225. name = tokenPairNode->mLeft->ToString() + tokenPairNode->mRight->ToString();
  226. }
  227. if (!name.empty())
  228. {
  229. if ((name == "class") || (name == "struct") || (name == "struct*") || (name == "const") || (name == "var"))
  230. {
  231. int prevFlags = genericParamDef->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr);
  232. if (prevFlags != 0)
  233. {
  234. String prevFlagName;
  235. if (prevFlags & BfGenericParamFlag_Class)
  236. prevFlagName = "class";
  237. else if (prevFlags & BfGenericParamFlag_Struct)
  238. prevFlagName = "struct";
  239. else //
  240. prevFlagName = "struct*";
  241. if (prevFlagName == name)
  242. mPassInstance->Fail(StrFormat("Cannot specify '%s' twice", prevFlagName.c_str()), constraintNode);
  243. else
  244. mPassInstance->Fail(StrFormat("Cannot specify both '%s' and '%s'", prevFlagName.c_str(), name.c_str()), constraintNode);
  245. return;
  246. }
  247. if (name == "class")
  248. genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Class);
  249. else if (name == "struct")
  250. genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Struct);
  251. else if (name == "struct*")
  252. genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_StructPtr);
  253. else if (name == "const")
  254. genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Const);
  255. else //if (name == "var")
  256. genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Var);
  257. continue;
  258. }
  259. else if (name == "new")
  260. {
  261. genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_New);
  262. continue;
  263. }
  264. else if (name == "delete")
  265. {
  266. genericParamDef->mGenericParamFlags = (BfGenericParamFlags)(genericParamDef->mGenericParamFlags | BfGenericParamFlag_Delete);
  267. continue;
  268. }
  269. }
  270. auto constraintType = BfNodeDynCast<BfTypeReference>(constraintNode);
  271. if (constraintType == NULL)
  272. {
  273. mPassInstance->Fail("Invalid constraint", constraintNode);
  274. return;
  275. }
  276. genericParamDef->mInterfaceConstraints.push_back(constraintType);
  277. }
  278. }
  279. }
  280. BfProtection BfDefBuilder::GetProtection(BfTokenNode* protectionToken)
  281. {
  282. if (protectionToken == NULL)
  283. {
  284. if (mCurTypeDef->mTypeCode == BfTypeCode_Interface)
  285. return BfProtection_Public;
  286. else
  287. return BfProtection_Private;
  288. }
  289. if (protectionToken->GetToken() == BfToken_Public)
  290. return BfProtection_Public;
  291. if (protectionToken->GetToken() == BfToken_Protected)
  292. return BfProtection_Protected;
  293. return BfProtection_Private;
  294. }
  295. void BfDefBuilder::Visit(BfConstructorDeclaration* ctorDeclaration)
  296. {
  297. if (!WantsNode(ctorDeclaration, NULL))
  298. return;
  299. Visit((BfMethodDeclaration*)ctorDeclaration);
  300. }
  301. BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaration, BfMethodDef* outerMethodDef)
  302. {
  303. BfMethodDef* methodDef;
  304. if (auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(methodDeclaration))
  305. {
  306. auto operatorDef = new BfOperatorDef();
  307. operatorDef->mOperatorDeclaration = operatorDecl;
  308. operatorDef->mIsOperator = true;
  309. methodDef = operatorDef;
  310. }
  311. else
  312. methodDef = new BfMethodDef();
  313. methodDef->mDeclaringType = mCurTypeDef;
  314. methodDef->mMethodDeclaration = methodDeclaration;
  315. methodDef->mExplicitInterface = methodDeclaration->mExplicitInterface;
  316. methodDef->mReturnTypeRef = methodDeclaration->mReturnType;
  317. methodDef->mProtection = GetProtection(methodDeclaration->mProtectionSpecifier);
  318. //if (mCurTypeDef->mIsPartial)
  319. //methodDef->mProtection = BfProtection_Public;
  320. if (methodDeclaration->mInternalSpecifier != NULL) // TODO: Do this properly
  321. methodDef->mProtection = BfProtection_Public;
  322. methodDef->mIsReadOnly = methodDeclaration->mReadOnlySpecifier != NULL;
  323. methodDef->mIsStatic = methodDeclaration->mStaticSpecifier != NULL;
  324. methodDef->mIsVirtual = methodDeclaration->mVirtualSpecifier != NULL;
  325. methodDef->mIsPartial = methodDeclaration->mPartialSpecifier != NULL;
  326. methodDef->mIsNew = methodDeclaration->mNewSpecifier != NULL;
  327. methodDef->mIsMutating = methodDeclaration->mMutSpecifier != NULL;
  328. methodDef->mIsExtern = methodDeclaration->mExternSpecifier != NULL;
  329. methodDef->mBody = methodDeclaration->mBody;
  330. HashContext signatureHashCtx;
  331. HashNode(signatureHashCtx, methodDeclaration, methodDef->mBody);
  332. //methodDef->mSignatureHash = signatureHashCtx.Finish128();
  333. if (mSignatureHashCtx != NULL)
  334. HashNode(*mSignatureHashCtx, methodDeclaration, methodDef->mBody);
  335. HashContext fullHash;
  336. HashNode(fullHash, methodDeclaration);
  337. methodDef->mFullHash = fullHash.Finish128();
  338. if (methodDeclaration->mVirtualSpecifier != NULL)
  339. {
  340. methodDef->mIsOverride = methodDeclaration->mVirtualSpecifier->GetToken() == BfToken_Override;
  341. methodDef->mIsAbstract = methodDeclaration->mVirtualSpecifier->GetToken() == BfToken_Abstract;
  342. if (methodDef->mIsOverride)
  343. mCurTypeDef->mHasOverrideMethods = true;
  344. if (methodDeclaration->mVirtualSpecifier->GetToken() == BfToken_Concrete)
  345. {
  346. methodDef->mIsConcrete = true;
  347. methodDef->mIsVirtual = false;
  348. }
  349. if (mCurTypeDef->mTypeCode == BfTypeCode_Interface)
  350. {
  351. if ((methodDef->mIsConcrete) && (!mCurTypeDef->mIsConcrete))
  352. mPassInstance->Fail("Only interfaces declared as 'concrete' can be declare methods as 'concrete'. Consider adding 'concrete' to the interface declaration.", methodDeclaration->mVirtualSpecifier);
  353. //if (!methodDef->mIsConcrete)
  354. //mPassInstance->Fail(StrFormat("Interfaces methods cannot be declared as '%s'", methodDeclaration->mVirtualSpecifier->ToString().c_str()), methodDeclaration->mVirtualSpecifier);
  355. }
  356. else
  357. {
  358. if (methodDef->mIsConcrete)
  359. mPassInstance->Fail("Only interfaces methods can be declared as 'concrete'", methodDeclaration->mVirtualSpecifier);
  360. }
  361. if (methodDef->mIsAbstract)
  362. {
  363. if ((!mCurTypeDef->mIsAbstract) && (mCurTypeDef->mTypeCode != BfTypeCode_Interface))
  364. mPassInstance->Fail("Method is abstract but it is contained in non-abstract class", methodDeclaration);
  365. if (methodDeclaration->mBody != NULL)
  366. mPassInstance->Fail("Abstract method cannot declare a body", methodDeclaration);
  367. }
  368. }
  369. else
  370. {
  371. methodDef->mIsOverride = false;
  372. methodDef->mIsAbstract = false;
  373. }
  374. if (mCurTypeDef->mTypeCode == BfTypeCode_Interface)
  375. {
  376. if ((!methodDef->mIsConcrete) && (!methodDef->mIsStatic) && (!methodDef->mGenericParams.empty()) && (methodDef->mProtection == BfProtection_Public))
  377. methodDef->mIsVirtual = true;
  378. }
  379. if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
  380. {
  381. methodDef->mIsMutating = true;
  382. methodDef->mMethodType = BfMethodType_Ctor;
  383. if (methodDef->mIsStatic)
  384. methodDef->mName = "__BfStaticCtor";
  385. else
  386. methodDef->mName = "__BfCtor";
  387. }
  388. else if (methodDeclaration->IsA<BfDestructorDeclaration>())
  389. {
  390. methodDef->mMethodType = BfMethodType_Dtor;
  391. if (methodDef->mIsStatic)
  392. methodDef->mName = "__BfStaticDtor";
  393. else
  394. {
  395. mCurTypeDef->mDtorDef = methodDef;
  396. methodDef->mName = "~this";
  397. if (!methodDef->mIsVirtual)
  398. {
  399. methodDef->mIsVirtual = true;
  400. methodDef->mIsOverride = true;
  401. }
  402. }
  403. }
  404. else if (auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(methodDeclaration))
  405. {
  406. methodDef->mMethodType = BfMethodType_Operator;
  407. /*if (propertyDecl->mStaticSpecifier == NULL)
  408. {
  409. mPassInstance->Fail("Operators must be declared as static", methodDeclaration);
  410. }*/
  411. String declError;
  412. if (methodDef->mProtection != BfProtection_Public)
  413. {
  414. declError = "'public'";
  415. methodDef->mProtection = BfProtection_Public; // Fix it
  416. }
  417. if (!methodDef->mIsStatic)
  418. {
  419. if (!declError.empty())
  420. declError += " and ";
  421. declError += "'static'";
  422. methodDef->mIsStatic = true; // Fix it
  423. }
  424. if (!declError.empty())
  425. {
  426. mPassInstance->Fail(StrFormat("Operator must be declared %s", declError.c_str()), operatorDecl->mOperatorToken);
  427. }
  428. }
  429. else if ((mCurTypeDef->mIsDelegate) || (mCurTypeDef->mIsFunction))
  430. {
  431. methodDef->mName = "Invoke";
  432. methodDef->mMethodType = BfMethodType_Normal;
  433. methodDef->mProtection = BfProtection_Public;
  434. methodDef->mIsStatic = mCurTypeDef->mIsFunction;
  435. auto attributes = mCurTypeDef->mTypeDeclaration->mAttributes;
  436. while (attributes != NULL)
  437. {
  438. if (attributes->mAttributeTypeRef != NULL)
  439. {
  440. auto typeRefName = attributes->mAttributeTypeRef->ToString();
  441. if (typeRefName == "StdCall")
  442. methodDef->mCallingConvention = BfCallingConvention_Stdcall;
  443. }
  444. attributes = attributes->mNextAttribute;
  445. }
  446. }
  447. else if (methodDeclaration->mMixinSpecifier != NULL)
  448. {
  449. if (methodDeclaration->mNameNode != NULL)
  450. methodDef->mName = methodDeclaration->mNameNode->ToString();
  451. methodDef->mMethodType = BfMethodType_Mixin;
  452. /*if (!methodDef->mIsStatic)
  453. mPassInstance->Fail("Mixin must be declared static", methodDeclaration->mMixinSpecifier);*/
  454. }
  455. else
  456. {
  457. if (methodDeclaration->mNameNode != NULL)
  458. methodDef->mName = methodDeclaration->mNameNode->ToString();
  459. methodDef->mMethodType = BfMethodType_Normal;
  460. }
  461. if (outerMethodDef != NULL)
  462. {
  463. for (auto genericParam : outerMethodDef->mGenericParams)
  464. {
  465. auto* copiedGenericParamDef = new BfGenericParamDef();
  466. *copiedGenericParamDef = *genericParam;
  467. methodDef->mGenericParams.Add(copiedGenericParamDef);
  468. }
  469. }
  470. int outerGenericSize = 0;
  471. if (outerMethodDef != NULL)
  472. outerGenericSize = (int)outerMethodDef->mGenericParams.size();
  473. ParseGenericParams(methodDeclaration->mGenericParams, methodDeclaration->mGenericConstraintsDeclaration, methodDef->mGenericParams, outerGenericSize);
  474. bool didDefaultsError = false;
  475. bool hadParams = false;
  476. bool hasDefault = false;
  477. for (int paramIdx = 0; paramIdx < (int) methodDeclaration->mParams.size(); paramIdx++)
  478. {
  479. BfParameterDeclaration* paramDecl = methodDeclaration->mParams[paramIdx];
  480. auto paramDef = new BfParameterDef();
  481. paramDef->mParamDeclaration = paramDecl;
  482. if (paramDecl->mNameNode != NULL)
  483. paramDef->mName = paramDecl->mNameNode->ToString();
  484. paramDef->mTypeRef = paramDecl->mTypeRef;
  485. paramDef->mMethodGenericParamIdx = mSystem->GetGenericParamIdx(methodDef->mGenericParams, paramDef->mTypeRef);
  486. if (paramDecl->mModToken == NULL)
  487. paramDef->mParamKind = BfParamKind_Normal;
  488. else //
  489. paramDef->mParamKind = BfParamKind_Params;
  490. if (paramDef->mParamDeclaration != NULL)
  491. {
  492. if (paramDef->mParamKind == BfParamKind_Params)
  493. {
  494. hadParams = true;
  495. }
  496. else if (hadParams)
  497. {
  498. methodDef->mParams[paramIdx - 1]->mParamKind = BfParamKind_Normal;
  499. hadParams = false;
  500. mPassInstance->Fail("Params parameter must be the last parameter", methodDef->mParams[paramIdx - 1]->mParamDeclaration);
  501. }
  502. if (paramDef->mParamDeclaration->mInitializer != NULL)
  503. hasDefault = true;
  504. else if (hasDefault)
  505. {
  506. if (!didDefaultsError)
  507. mPassInstance->Fail("Optional parameters must appear after all required parameters", methodDef->mParams[paramIdx - 1]->mParamDeclaration);
  508. didDefaultsError = true;
  509. }
  510. }
  511. methodDef->mParams.push_back(paramDef);
  512. }
  513. ParseAttributes(methodDeclaration->mAttributes, methodDef);
  514. return methodDef;
  515. }
  516. void BfDefBuilder::Visit(BfMethodDeclaration* methodDeclaration)
  517. {
  518. if (mCurTypeDef == NULL)
  519. {
  520. return;
  521. }
  522. int addLen = 0;
  523. if ((methodDeclaration->mNameNode == NULL) && (methodDeclaration->mBody == NULL))
  524. addLen = 1;
  525. mSystem->CheckLockYield();
  526. bool wantsBody = true;
  527. BfAstNode* startNode = methodDeclaration->mReturnType;
  528. if (startNode == NULL)
  529. startNode = methodDeclaration->mMixinSpecifier;
  530. if (startNode == NULL)
  531. {
  532. if (auto ctorDecl = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
  533. startNode = ctorDecl->mThisToken;
  534. else if (auto ctorDecl = BfNodeDynCast<BfDestructorDeclaration>(methodDeclaration))
  535. startNode = ctorDecl->mTildeToken;
  536. }
  537. if (startNode == NULL)
  538. startNode = methodDeclaration->mOpenParen;
  539. if (!WantsNode(methodDeclaration, startNode, addLen))
  540. {
  541. if (!WantsNode(methodDeclaration, NULL, addLen))
  542. return;
  543. wantsBody = false;
  544. }
  545. auto methodDef = CreateMethodDef(methodDeclaration);
  546. if (methodDef->mMethodType == BfMethodType_Operator)
  547. {
  548. mCurTypeDef->mOperators.push_back((BfOperatorDef*)methodDef);
  549. }
  550. mCurTypeDef->mMethods.push_back(methodDef);
  551. methodDef->mWantsBody = wantsBody;
  552. }
  553. void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef)
  554. {
  555. while (attributes != NULL)
  556. {
  557. if (attributes->mAttributeTypeRef != NULL)
  558. {
  559. auto typeRefName = attributes->mAttributeTypeRef->ToString();
  560. if (typeRefName == "CLink")
  561. methodDef->mCLink = true;
  562. else if (typeRefName == "StdCall")
  563. methodDef->mCallingConvention = BfCallingConvention_Stdcall;
  564. else if (typeRefName == "CVarArgs")
  565. methodDef->mCallingConvention = BfCallingConvention_CVarArgs;
  566. else if (typeRefName == "Inline")
  567. methodDef->mAlwaysInline = true;
  568. else if (typeRefName == "AllowAppend")
  569. methodDef->mHasAppend = true;
  570. else if (typeRefName == "Checked")
  571. methodDef->mCheckedKind = BfCheckedKind_Checked;
  572. else if (typeRefName == "Unchecked")
  573. methodDef->mCheckedKind = BfCheckedKind_Unchecked;
  574. else if (typeRefName == "Export")
  575. {
  576. mCurTypeDef->mIsAlwaysInclude = true;
  577. methodDef->mImportKind = BfImportKind_Export;
  578. }
  579. else if (typeRefName == "Import")
  580. {
  581. methodDef->mImportKind = BfImportKind_Static;
  582. if (!attributes->mArguments.IsEmpty())
  583. {
  584. if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(attributes->mArguments[0]))
  585. {
  586. if (literalExpr->mValue.mTypeCode == BfTypeCode_CharPtr)
  587. {
  588. String filePath = *literalExpr->mValue.mString;
  589. String fileExt = GetFileExtension(filePath);
  590. if ((fileExt.Equals(".DLL", StringImpl::CompareKind_OrdinalIgnoreCase)) ||
  591. (fileExt.Equals(".EXE", StringImpl::CompareKind_OrdinalIgnoreCase)))
  592. {
  593. methodDef->mImportKind = BfImportKind_Dynamic;
  594. }
  595. }
  596. }
  597. }
  598. }
  599. else if (typeRefName == "NoReturn")
  600. methodDef->mNoReturn = true;
  601. else if (typeRefName == "SkipCall")
  602. methodDef->mIsSkipCall = true;
  603. else if (typeRefName == "NoShow")
  604. methodDef->mIsNoShow = true;
  605. else if (typeRefName == "NoDiscard")
  606. methodDef->mIsNoDiscard = true;
  607. }
  608. attributes = attributes->mNextAttribute;
  609. }
  610. }
  611. void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfTypeDef* typeDef)
  612. {
  613. while (attributes != NULL)
  614. {
  615. if (attributes->mAttributeTypeRef != NULL)
  616. {
  617. auto typeRefName = attributes->mAttributeTypeRef->ToString();
  618. if (typeRefName == "AlwaysInclude")
  619. typeDef->mIsAlwaysInclude = true;
  620. else if (typeRefName == "NoDiscard")
  621. typeDef->mIsNoDiscard = true;
  622. }
  623. attributes = attributes->mNextAttribute;
  624. }
  625. }
  626. void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration)
  627. {
  628. int addLen = 0;
  629. if (propertyDeclaration->mTypeRef == NULL)
  630. addLen = 1;
  631. bool wantsBody = true;
  632. if (!WantsNode(propertyDeclaration, propertyDeclaration->mTypeRef, addLen))
  633. {
  634. if (!WantsNode(propertyDeclaration, NULL, addLen))
  635. return;
  636. // The cursor is inside some exterior specifiers, don't process body
  637. wantsBody = false;
  638. }
  639. if (propertyDeclaration->mConstSpecifier != NULL)
  640. {
  641. mPassInstance->Fail("Const properties are not allowed", propertyDeclaration->mConstSpecifier);
  642. }
  643. HashNode(*mSignatureHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock);
  644. BfPropertyDef* propertyDef = new BfPropertyDef();
  645. mCurTypeDef->mProperties.push_back(propertyDef);
  646. propertyDef->mProtection = GetProtection(propertyDeclaration->mProtectionSpecifier);
  647. if (propertyDeclaration->mInternalSpecifier != NULL) // TODO: Do this properly
  648. propertyDef->mProtection = BfProtection_Public;
  649. propertyDef->mIdx = (int)mCurTypeDef->mProperties.size() - 1;
  650. propertyDef->mIsConst = false;
  651. propertyDef->mIsStatic = propertyDeclaration->mStaticSpecifier != NULL;
  652. propertyDef->mIsReadOnly = propertyDeclaration->mReadOnlySpecifier != NULL;
  653. if (propertyDeclaration->mNameNode != NULL)
  654. propertyDef->mName = propertyDeclaration->mNameNode->ToString();
  655. else if (propertyDeclaration->IsA<BfIndexerDeclaration>())
  656. {
  657. propertyDef->mName = "[]";
  658. }
  659. propertyDef->mTypeRef = propertyDeclaration->mTypeRef;
  660. propertyDef->mInitializer = NULL;
  661. propertyDef->mFieldDeclaration = propertyDeclaration;
  662. propertyDef->mDeclaringType = mCurTypeDef;
  663. //HashNode(*mSignatureHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock);
  664. //mCurTypeDef->mSignatureHash = HashNode(propertyDeclaration, propertyDeclaration->mDefinitionBlock, mCurTypeDef->mSignatureHash);
  665. if (propertyDeclaration->mDefinitionBlock == NULL) // To differentiate between autocompleting partial property if it transitions to a field
  666. {
  667. //mCurTypeDef->mSignatureHash = HashString("nullprop", mCurTypeDef->mSignatureHash);
  668. mSignatureHashCtx->MixinStr("nullprop");
  669. }
  670. auto indexerDeclaration = BfNodeDynCast<BfIndexerDeclaration>(propertyDeclaration);
  671. bool isAbstract = false;
  672. if (propertyDeclaration->mVirtualSpecifier != NULL)
  673. isAbstract = propertyDeclaration->mVirtualSpecifier->GetToken() == BfToken_Abstract;
  674. bool needsAutoProperty = mCurTypeDef->HasAutoProperty(propertyDeclaration);
  675. if (needsAutoProperty)
  676. {
  677. BfFieldDef* fieldDef = new BfFieldDef();
  678. fieldDef->mDeclaringType = mCurTypeDef;
  679. fieldDef->mFieldDeclaration = propertyDeclaration;
  680. fieldDef->mProtection = BfProtection_Hidden;
  681. fieldDef->mIsStatic = propertyDef->mIsStatic;
  682. fieldDef->mTypeRef = propertyDef->mTypeRef;
  683. if (auto refTypeRef = BfNodeDynCast<BfRefTypeRef>(fieldDef->mTypeRef))
  684. fieldDef->mTypeRef = refTypeRef->mElementType;
  685. fieldDef->mName = mCurTypeDef->GetAutoPropertyName(propertyDeclaration);
  686. fieldDef->mIdx = (int)mCurTypeDef->mFields.size();
  687. mCurTypeDef->mFields.push_back(fieldDef);
  688. mCurTypeDef->mSignatureHash = HashString(fieldDef->mName, mCurTypeDef->mSignatureHash);
  689. }
  690. for (auto methodDeclaration : propertyDeclaration->mMethods)
  691. {
  692. HashNode(*mSignatureHashCtx, methodDeclaration->mAttributes);
  693. HashNode(*mSignatureHashCtx, methodDeclaration->mProtectionSpecifier);
  694. HashNode(*mSignatureHashCtx, methodDeclaration->mNameNode);
  695. HashNode(*mSignatureHashCtx, methodDeclaration->mMutSpecifier);
  696. if (!wantsBody)
  697. continue;
  698. if (!WantsNode(methodDeclaration))
  699. continue;
  700. auto methodDef = new BfMethodDef();
  701. mCurTypeDef->mMethods.push_back(methodDef);
  702. methodDef->mDeclaringType = mCurTypeDef;
  703. methodDef->mMethodDeclaration = methodDeclaration;
  704. methodDef->mProtection = propertyDef->mProtection;
  705. methodDef->mWantsBody = (methodDeclaration->mBody != NULL) && (WantsNode(methodDeclaration->mBody));
  706. if (methodDeclaration->mProtectionSpecifier != NULL)
  707. {
  708. BfProtection newProtection = GetProtection(methodDeclaration->mProtectionSpecifier);
  709. if (newProtection > methodDef->mProtection)
  710. mPassInstance->Fail(StrFormat("the accessibility modifier of the 'get' accessor must be more restrictive than the property or indexer '%s'", propertyDef->mName.c_str()),
  711. methodDeclaration->mProtectionSpecifier);
  712. methodDef->mProtection = newProtection;
  713. }
  714. methodDef->mIsMutating = methodDeclaration->mMutSpecifier != NULL;
  715. methodDef->mIsAbstract = isAbstract;
  716. methodDef->mIsStatic = propertyDef->mIsStatic;
  717. methodDef->mIsVirtual = propertyDeclaration->mVirtualSpecifier != NULL;
  718. methodDef->mIsExtern = propertyDeclaration->mExternSpecifier != NULL;
  719. methodDef->mMethodDeclaration = methodDeclaration;
  720. methodDef->mExplicitInterface = propertyDeclaration->mExplicitInterface;
  721. HashContext propHashCtx;
  722. HashNode(propHashCtx, methodDeclaration->mNameNode);
  723. HashNode(propHashCtx, methodDeclaration->mAttributes);
  724. HashNode(propHashCtx, methodDeclaration->mProtectionSpecifier);
  725. HashNode(propHashCtx, methodDeclaration->mMutSpecifier);
  726. HashNode(propHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock);
  727. //methodDef->mSignatureHash = propHashCtx.Finish128();
  728. methodDef->mFullHash = HashNode(propertyDeclaration);
  729. if (propertyDeclaration->mVirtualSpecifier != NULL)
  730. methodDef->mIsOverride = propertyDeclaration->mVirtualSpecifier->GetToken() == BfToken_Override;
  731. else
  732. methodDef->mIsOverride = false;
  733. methodDef->mIsNew = propertyDeclaration->mNewSpecifier != NULL;
  734. if (indexerDeclaration != NULL)
  735. {
  736. for (int paramIdx = 0; paramIdx < (int)indexerDeclaration->mParams.size(); paramIdx++)
  737. {
  738. auto paramDef = new BfParameterDef();
  739. BfParameterDeclaration* paramDecl = indexerDeclaration->mParams[paramIdx];
  740. paramDef->mParamDeclaration = paramDecl;
  741. paramDef->mName = paramDecl->mNameNode->ToString();
  742. paramDef->mTypeRef = paramDecl->mTypeRef;
  743. paramDef->mMethodGenericParamIdx = mSystem->GetGenericParamIdx(methodDef->mGenericParams, paramDef->mTypeRef);
  744. methodDef->mParams.push_back(paramDef);
  745. }
  746. }
  747. String methodName;
  748. if (auto propExprBody = BfNodeDynCast<BfPropertyBodyExpression>(propertyDeclaration->mDefinitionBlock))
  749. methodName = "get";
  750. else if ((methodDeclaration != NULL) && (methodDeclaration->mNameNode != NULL))
  751. methodName = methodDeclaration->mNameNode->ToString();
  752. if (methodName == "get")
  753. {
  754. methodDef->mName = "get__";
  755. if (propertyDeclaration->mNameNode != NULL)
  756. methodDef->mName += propertyDeclaration->mNameNode->ToString();
  757. methodDef->mReturnTypeRef = propertyDeclaration->mTypeRef;
  758. methodDef->mMethodType = BfMethodType_PropertyGetter;
  759. if (propertyDeclaration->mReadOnlySpecifier != NULL)
  760. methodDef->mIsReadOnly = true;
  761. propertyDef->mMethods.Add(methodDef);
  762. }
  763. else if (methodName == "set")
  764. {
  765. methodDef->mName = "set__";
  766. if (propertyDeclaration->mNameNode != NULL)
  767. methodDef->mName += propertyDeclaration->mNameNode->ToString();
  768. methodDef->mMethodType = BfMethodType_PropertySetter;
  769. if (BfNodeDynCast<BfTokenNode>(methodDeclaration->mBody) != NULL)
  770. methodDef->mIsMutating = true; // Don't require "set mut;", just "set;"
  771. auto paramDef = new BfParameterDef();
  772. paramDef->mName = "value";
  773. if (auto refTypeRef = BfNodeDynCast<BfRefTypeRef>(propertyDeclaration->mTypeRef))
  774. paramDef->mTypeRef = refTypeRef->mElementType;
  775. else
  776. paramDef->mTypeRef = propertyDeclaration->mTypeRef;
  777. methodDef->mParams.push_back(paramDef);
  778. propertyDef->mMethods.Add(methodDef);
  779. }
  780. else
  781. {
  782. // Parse had an error, leave this block as an unnamed method
  783. }
  784. methodDef->mBody = methodDeclaration->mBody;
  785. ParseAttributes(methodDeclaration->mAttributes, methodDef);
  786. }
  787. }
  788. void BfDefBuilder::Visit(BfFieldDeclaration* fieldDeclaration)
  789. {
  790. mSystem->CheckLockYield();
  791. int endingAdd = 1;// Add '1' for autocompletion of 'new' initializer
  792. if (!WantsNode(fieldDeclaration, NULL, endingAdd))
  793. {
  794. return;
  795. }
  796. // This check is a bit of a hack to determine the difference between a "MemberType mMember" and a proper case entry of "mMember(TupleType)"
  797. bool isEnumEntryDecl = fieldDeclaration->IsA<BfEnumEntryDeclaration>();
  798. auto fieldDef = new BfFieldDef();
  799. mCurTypeDef->mFields.push_back(fieldDef);
  800. fieldDef->mFieldDeclaration = fieldDeclaration;
  801. fieldDef->mDeclaringType = mCurTypeDef;
  802. if (fieldDeclaration->mNameNode != NULL)
  803. fieldDef->mName = fieldDeclaration->mNameNode->ToString();
  804. fieldDef->mProtection = GetProtection(fieldDeclaration->mProtectionSpecifier);
  805. if (mCurTypeDef->mIsPartial)
  806. fieldDef->mProtection = BfProtection_Public;
  807. else if (isEnumEntryDecl)
  808. fieldDef->mProtection = BfProtection_Public;
  809. if (fieldDeclaration->mInternalSpecifier != NULL) // TODO: Do this properly
  810. fieldDef->mProtection = BfProtection_Public;
  811. fieldDef->mIsReadOnly = fieldDeclaration->mReadOnlySpecifier != NULL;
  812. fieldDef->mIsInline = (fieldDeclaration->mReadOnlySpecifier != NULL) && (fieldDeclaration->mReadOnlySpecifier->GetToken() == BfToken_Inline);
  813. fieldDef->mIsExtern = (fieldDeclaration->mExternSpecifier != NULL);
  814. fieldDef->mIsConst = (fieldDeclaration->mConstSpecifier != NULL) || (isEnumEntryDecl);
  815. fieldDef->mIsStatic = (fieldDeclaration->mStaticSpecifier != NULL) || fieldDef->mIsConst;
  816. fieldDef->mIsVolatile = (fieldDeclaration->mVolatileSpecifier != NULL);
  817. fieldDef->mTypeRef = fieldDeclaration->mTypeRef;
  818. if ((mCurTypeDef->mTypeCode == BfTypeCode_Enum) && (fieldDef->mTypeRef != NULL) && (!fieldDef->mIsStatic))
  819. {
  820. // This check is a bit of a hack to determine the difference between a "MemberType mMember" and a proper case entry of "mMember(TupleType)"
  821. if (!isEnumEntryDecl)
  822. {
  823. mPassInstance->Fail("Non-static field declarations are not allowed in enums", fieldDeclaration);
  824. }
  825. }
  826. fieldDef->mIdx = (int)mCurTypeDef->mFields.size() - 1;
  827. fieldDef->mInitializer = fieldDeclaration->mInitializer;
  828. //mCurTypeDef->mSignatureHash = HashNode(fieldDeclaration, mCurTypeDef->mSignatureHash);
  829. HashNode(*mSignatureHashCtx, fieldDeclaration);
  830. }
  831. void BfDefBuilder::Visit(BfEnumCaseDeclaration* enumCaseDeclaration)
  832. {
  833. if (!WantsNode(enumCaseDeclaration, enumCaseDeclaration->mCaseToken, 0))
  834. {
  835. return;
  836. }
  837. for (int entryIdx = 0; entryIdx < (int)enumCaseDeclaration->mEntries.size(); entryIdx++)
  838. {
  839. auto caseEntry = enumCaseDeclaration->mEntries[entryIdx];
  840. Visit(caseEntry);
  841. }
  842. }
  843. BfFieldDef* BfDefBuilder::AddField(BfTypeDef* typeDef, BfTypeReference* fieldType, const StringImpl& fieldName)
  844. {
  845. BfFieldDef* fieldDef = new BfFieldDef();
  846. fieldDef->mDeclaringType = typeDef;
  847. fieldDef->mTypeRef = fieldType;
  848. fieldDef->mName = fieldName;
  849. fieldDef->mIdx = (int)typeDef->mFields.size();
  850. typeDef->mFields.push_back(fieldDef);
  851. return fieldDef;
  852. }
  853. BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType, BfProtection protection, bool isStatic, const StringImpl& name)
  854. {
  855. BF_ASSERT(typeDef->mTypeCode != BfTypeCode_TypeAlias);
  856. auto methodDef = new BfMethodDef();
  857. methodDef->mIdx = (int)typeDef->mMethods.size();
  858. typeDef->mMethods.push_back(methodDef);
  859. methodDef->mDeclaringType = typeDef;
  860. methodDef->mMethodType = methodType;
  861. if (name.empty())
  862. {
  863. if (methodType == BfMethodType_Ctor)
  864. {
  865. if (isStatic)
  866. methodDef->mName = "__BfStaticCtor";
  867. else
  868. methodDef->mName = "__BfCtor";
  869. }
  870. else if (methodType == BfMethodType_CtorNoBody)
  871. {
  872. methodDef->mName = "__BfCtorNoBody";
  873. methodDef->mNoReflect = true;
  874. }
  875. else if (methodType == BfMethodType_CtorClear)
  876. {
  877. methodDef->mName = "__BfCtorClear";
  878. methodDef->mNoReflect = true;
  879. }
  880. else if (methodType == BfMethodType_Dtor)
  881. {
  882. if (isStatic)
  883. {
  884. methodDef->mName = "__BfStaticDtor";
  885. }
  886. else
  887. {
  888. methodDef->mName = "~this";
  889. methodDef->mIsVirtual = true;
  890. methodDef->mIsOverride = true;
  891. BF_ASSERT(typeDef->mDtorDef == NULL);
  892. typeDef->mDtorDef = methodDef;
  893. }
  894. }
  895. else
  896. {
  897. BF_FATAL("Method name expected");
  898. }
  899. }
  900. else
  901. methodDef->mName = name;
  902. methodDef->mProtection = protection;
  903. methodDef->mIsStatic = isStatic;
  904. return methodDef;
  905. }
  906. BfMethodDef* BfDefBuilder::AddDtor(BfTypeDef* typeDef)
  907. {
  908. auto methodDef = new BfMethodDef();
  909. typeDef->mMethods.push_back(methodDef);
  910. methodDef->mDeclaringType = typeDef;
  911. methodDef->mName = "~this";
  912. methodDef->mProtection = BfProtection_Public;
  913. methodDef->mMethodType = BfMethodType_Dtor;
  914. methodDef->mIsVirtual = true;
  915. methodDef->mIsOverride = true;
  916. BF_ASSERT(typeDef->mDtorDef == NULL);
  917. typeDef->mDtorDef = methodDef;
  918. return methodDef;
  919. }
  920. void BfDefBuilder::AddDynamicCastMethods(BfTypeDef* typeDef)
  921. {
  922. //
  923. {
  924. auto methodDef = new BfMethodDef();
  925. methodDef->mIdx = (int)typeDef->mMethods.size();
  926. typeDef->mMethods.push_back(methodDef);
  927. methodDef->mDeclaringType = typeDef;
  928. methodDef->mName = BF_METHODNAME_DYNAMICCAST;
  929. methodDef->mProtection = BfProtection_Protected;
  930. methodDef->mIsStatic = false;
  931. methodDef->mMethodType = BfMethodType_Normal;
  932. methodDef->mIsVirtual = true;
  933. methodDef->mIsOverride = true;
  934. auto paramDef = new BfParameterDef();
  935. paramDef->mName = "id";
  936. paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef;
  937. methodDef->mParams.push_back(paramDef);
  938. methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef;
  939. methodDef->mNoReflect = true;
  940. }
  941. //
  942. {
  943. auto methodDef = new BfMethodDef();
  944. methodDef->mIdx = (int)typeDef->mMethods.size();
  945. typeDef->mMethods.push_back(methodDef);
  946. methodDef->mDeclaringType = typeDef;
  947. methodDef->mName = BF_METHODNAME_DYNAMICCAST_INTERFACE;
  948. methodDef->mProtection = BfProtection_Protected;
  949. methodDef->mIsStatic = false;
  950. methodDef->mMethodType = BfMethodType_Normal;
  951. methodDef->mIsVirtual = true;
  952. methodDef->mIsOverride = true;
  953. auto paramDef = new BfParameterDef();
  954. paramDef->mName = "id";
  955. paramDef->mTypeRef = typeDef->mSystem->mDirectInt32TypeRef;
  956. methodDef->mParams.push_back(paramDef);
  957. methodDef->mReturnTypeRef = typeDef->mSystem->mDirectObjectTypeRef;
  958. methodDef->mNoReflect = true;
  959. }
  960. }
  961. void BfDefBuilder::AddParam(BfMethodDef* methodDef, BfTypeReference* typeRef, const StringImpl& paramName)
  962. {
  963. auto paramDef = new BfParameterDef();
  964. paramDef->mName = paramName;
  965. paramDef->mTypeRef = typeRef;
  966. methodDef->mParams.push_back(paramDef);
  967. }
  968. void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
  969. {
  970. BF_ASSERT(typeDeclaration->GetSourceData() == mCurSource->mSourceData);
  971. if ((typeDeclaration->mTypeNode != NULL) && (typeDeclaration->mNameNode == NULL))
  972. return;
  973. /*if (typeDeclaration->mNameNode != NULL)
  974. OutputDebugStrF("Decl: %s\n", typeDeclaration->mNameNode->ToString().c_str());*/
  975. bool isAutoCompleteTempType = false;
  976. if (mResolvePassData != NULL)
  977. {
  978. isAutoCompleteTempType = (mResolvePassData->mAutoComplete != NULL);
  979. int cursorIdx = mResolvePassData->mParser->mCursorIdx;
  980. if (typeDeclaration->Contains(cursorIdx, 1, 0))
  981. {
  982. // Within bounds
  983. }
  984. else if (cursorIdx != -1)
  985. return;
  986. }
  987. int curLine = 0;
  988. int curColumn = 0;
  989. auto bfParser = mCurSource->ToParser();
  990. if (bfParser != NULL)
  991. {
  992. int srcStart = typeDeclaration->GetSrcStart();
  993. auto* jumpEntry = bfParser->mJumpTable + (srcStart / PARSER_JUMPTABLE_DIVIDE);
  994. if (jumpEntry->mCharIdx > srcStart)
  995. jumpEntry--;
  996. curLine = jumpEntry->mLineNum;
  997. int curSrcPos = jumpEntry->mCharIdx;
  998. curColumn = 0;
  999. while (curSrcPos < srcStart)
  1000. {
  1001. if (bfParser->mSrc[curSrcPos] == '\n')
  1002. {
  1003. curLine++;
  1004. curColumn = 0;
  1005. }
  1006. else
  1007. curColumn++;
  1008. curSrcPos++;
  1009. }
  1010. }
  1011. auto outerTypeDef = mCurTypeDef;
  1012. auto actualOuterTypeDef = mCurActualTypeDef;
  1013. mCurTypeDef = new BfTypeDef();
  1014. mCurActualTypeDef = mCurTypeDef;
  1015. mCurTypeDef->mSystem = mSystem;
  1016. mCurTypeDef->mProject = mCurSource->mProject;
  1017. mCurTypeDef->mNamespace = mNamespace;
  1018. mSystem->AddNamespaceUsage(mCurTypeDef->mNamespace, mCurTypeDef->mProject);
  1019. if (typeDeclaration->mTypeNode == NULL)
  1020. {
  1021. mCurTypeDef->mIsPartial = true;
  1022. mCurTypeDef->mIsExplicitPartial = true;
  1023. }
  1024. if (typeDeclaration->mNameNode == NULL)
  1025. {
  1026. // Global
  1027. mCurTypeDef->mName = mSystem->mGlobalsAtom;
  1028. mCurTypeDef->mName->Ref();
  1029. BF_ASSERT(mCurTypeDef->mSystem != NULL);
  1030. }
  1031. else
  1032. {
  1033. mCurTypeDef->mName = mSystem->GetAtom(typeDeclaration->mNameNode->ToString());
  1034. if (mCurTypeDef->mName->mIsSystemType)
  1035. {
  1036. mPassInstance->Fail(StrFormat("Type name '%s' is reserved", typeDeclaration->mNameNode->ToString().c_str()), typeDeclaration->mNameNode);
  1037. }
  1038. }
  1039. BfLogSys(mCurSource->mSystem, "DefBuilder %p TypeDecl:%s\n", mCurSource, mCurTypeDef->mName->ToString().mPtr);
  1040. mCurTypeDef->mProtection = (outerTypeDef == NULL) ? BfProtection_Public : BfProtection_Private;
  1041. if (typeDeclaration->mInternalSpecifier != NULL)
  1042. mCurTypeDef->mProtection = BfProtection_Public;
  1043. if (typeDeclaration->mProtectionSpecifier != NULL)
  1044. {
  1045. if ((outerTypeDef == NULL) && (typeDeclaration->mProtectionSpecifier->GetToken() != BfToken_Public))
  1046. {
  1047. //CS1527
  1048. mPassInstance->Fail("Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal", typeDeclaration->mProtectionSpecifier);
  1049. }
  1050. else
  1051. {
  1052. mCurTypeDef->mProtection = GetProtection(typeDeclaration->mProtectionSpecifier);
  1053. }
  1054. }
  1055. if (typeDeclaration->mAttributes != NULL)
  1056. ParseAttributes(typeDeclaration->mAttributes, mCurTypeDef);
  1057. for (auto& baseClass : typeDeclaration->mBaseClasses)
  1058. mCurTypeDef->mBaseTypes.push_back(baseClass);
  1059. HashContext fullHashCtx;
  1060. HashContext signatureHashCtx;
  1061. SetAndRestoreValue<HashContext*> prevFullHashCtx(mFullHashCtx, &fullHashCtx);
  1062. SetAndRestoreValue<HashContext*> prevSignatureHashCtx(mSignatureHashCtx, &signatureHashCtx);
  1063. if (bfParser != NULL)
  1064. mSignatureHashCtx->MixinStr(bfParser->mFileName);
  1065. HashNode(*mSignatureHashCtx, typeDeclaration->mTypeNode);
  1066. for (auto& baseClassNode : typeDeclaration->mBaseClasses)
  1067. HashNode(*mSignatureHashCtx, baseClassNode);
  1068. HashNode(*mSignatureHashCtx, typeDeclaration->mAttributes);
  1069. HashNode(*mSignatureHashCtx, typeDeclaration->mAbstractSpecifier);
  1070. HashNode(*mSignatureHashCtx, typeDeclaration->mSealedSpecifier);
  1071. HashNode(*mSignatureHashCtx, typeDeclaration->mInternalSpecifier);
  1072. HashNode(*mSignatureHashCtx, typeDeclaration->mProtectionSpecifier);
  1073. HashNode(*mSignatureHashCtx, typeDeclaration->mPartialSpecifier);
  1074. HashNode(*mSignatureHashCtx, typeDeclaration->mNameNode);
  1075. HashNode(*mSignatureHashCtx, typeDeclaration->mGenericParams);
  1076. HashNode(*mSignatureHashCtx, typeDeclaration->mGenericConstraintsDeclaration);
  1077. HashNode(*mFullHashCtx, typeDeclaration);
  1078. // Allow internal preprocessor flags to change a full hash change
  1079. if (bfParser != NULL)
  1080. {
  1081. // Note- we insert strings from these HashSets in bucket-order, which is stable
  1082. // for the same insertion order, but is not truly order independent. Shouldn't matter.
  1083. fullHashCtx.Mixin(bfParser->mParserData->mDefines_Def.size());
  1084. for (auto& defStr : bfParser->mParserData->mDefines_Def)
  1085. fullHashCtx.MixinStr(defStr);
  1086. fullHashCtx.Mixin(bfParser->mParserData->mDefines_NoDef.size());
  1087. for (auto& defStr : bfParser->mParserData->mDefines_NoDef)
  1088. fullHashCtx.MixinStr(defStr);
  1089. }
  1090. // We need to hash the position of the declaration in the file so we can rebuild the debug info with revised line numbers
  1091. int hashPos[2] = { curLine, curColumn };
  1092. mFullHashCtx->Mixin(hashPos);
  1093. if (auto typeAliasDeclaration = BfNodeDynCast<BfTypeAliasDeclaration>(typeDeclaration))
  1094. {
  1095. HashNode(*mSignatureHashCtx, typeAliasDeclaration->mAliasToType);
  1096. }
  1097. //TODO:
  1098. //int randomCrap = rand();
  1099. //HASH128_MIXIN(mCurTypeDef->mFullHash, randomCrap);
  1100. // To cause a type rebuild when we change pragma settings or #if resolves
  1101. //mCurTypeDef->mFullHash = Hash128(&typeDeclaration->mParser->mStateHash, sizeof(Val128), mCurTypeDef->mFullHash);
  1102. //BfParser* bfParser = typeDeclaration->mParser;
  1103. // Hash in ignored warnings that occur before our type declaration
  1104. std::set<int> ignoredWarningSet;
  1105. auto warningItr = bfParser->mParserData->mWarningEnabledChanges.begin();
  1106. while (warningItr != bfParser->mParserData->mWarningEnabledChanges.end())
  1107. {
  1108. int srcIdx = warningItr->mKey;
  1109. if (srcIdx >= typeDeclaration->GetSrcStart())
  1110. break;
  1111. auto& warningEntry = warningItr->mValue;
  1112. if (!warningEntry.mEnable)
  1113. {
  1114. ignoredWarningSet.insert(warningEntry.mWarningNumber);
  1115. }
  1116. else
  1117. {
  1118. auto setItr = ignoredWarningSet.find(warningEntry.mWarningNumber);
  1119. if (setItr != ignoredWarningSet.end())
  1120. ignoredWarningSet.erase(setItr);
  1121. }
  1122. ++warningItr;
  1123. }
  1124. for (auto ignoredWarning : ignoredWarningSet)
  1125. {
  1126. mFullHashCtx->Mixin(ignoredWarning);
  1127. }
  1128. // Hash in relative mPreprocessorIgnoredSectionStarts positions that occur within the type declaration
  1129. auto ignoredSectionItr = bfParser->mPreprocessorIgnoredSectionStarts.upper_bound(typeDeclaration->GetSrcStart());
  1130. while (ignoredSectionItr != bfParser->mPreprocessorIgnoredSectionStarts.end())
  1131. {
  1132. int srcIdx = *ignoredSectionItr;
  1133. if (srcIdx >= typeDeclaration->GetSrcEnd())
  1134. break;
  1135. int relSrcIdx = srcIdx - typeDeclaration->GetSrcStart();
  1136. mFullHashCtx->Mixin(relSrcIdx);
  1137. ++ignoredSectionItr;
  1138. }
  1139. SizedArray<BfAtom*, 6> expandedName;
  1140. if (mCurTypeDef->mName != mSystem->mGlobalsAtom)
  1141. expandedName.push_back(mCurTypeDef->mName);
  1142. // Expanded name should container outer namespace parts
  1143. if (outerTypeDef != NULL)
  1144. {
  1145. mCurTypeDef->mNestDepth = outerTypeDef->mNestDepth + 1;
  1146. mCurTypeDef->mNamespaceSearch = outerTypeDef->mNamespaceSearch;
  1147. mCurTypeDef->mStaticSearch = outerTypeDef->mStaticSearch;
  1148. for (auto outerGenericParamDef : outerTypeDef->mGenericParamDefs)
  1149. {
  1150. BfGenericParamDef* copiedGenericParamDef = new BfGenericParamDef();
  1151. *copiedGenericParamDef = *outerGenericParamDef;
  1152. mCurTypeDef->mGenericParamDefs.Add(copiedGenericParamDef);
  1153. }
  1154. BfTypeDef* parentType = outerTypeDef;
  1155. while (parentType != NULL)
  1156. {
  1157. expandedName.Insert(0, parentType->mNameEx);
  1158. parentType = parentType->mOuterType;
  1159. }
  1160. }
  1161. else
  1162. {
  1163. BF_ASSERT(mCurTypeDef->mNamespaceSearch.size() == 0);
  1164. mCurTypeDef->mNamespaceSearch = mNamespaceSearch;
  1165. mCurTypeDef->mStaticSearch = mStaticSearch;
  1166. }
  1167. // We need to mix the namespace search into the signature hash because it can change how type references are resolved
  1168. for (auto& usingName : mCurTypeDef->mNamespaceSearch)
  1169. {
  1170. mSystem->RefAtomComposite(usingName);
  1171. mSignatureHashCtx->MixinStr(usingName.ToString());
  1172. }
  1173. for (auto& usingName : mCurTypeDef->mStaticSearch)
  1174. {
  1175. HashNode(*mSignatureHashCtx, usingName);
  1176. }
  1177. if ((typeDeclaration->mPartialSpecifier != NULL) && (!isAutoCompleteTempType))
  1178. {
  1179. mCurTypeDef->mIsExplicitPartial = true;
  1180. mCurTypeDef->mIsPartial = true;
  1181. }
  1182. bool isExtension = false;
  1183. if ((typeDeclaration->mTypeNode != NULL) && (typeDeclaration->mTypeNode->GetToken() == BfToken_Extension))
  1184. {
  1185. mCurTypeDef->mIsPartial = true;
  1186. isExtension = true;
  1187. }
  1188. BfAtomComposite fullName;
  1189. if (!expandedName.IsEmpty())
  1190. fullName.Set(mCurTypeDef->mNamespace.mParts, mCurTypeDef->mNamespace.mSize, &expandedName[0], (int)expandedName.size());
  1191. else
  1192. fullName = mCurTypeDef->mNamespace;
  1193. String fullNameStr = fullName.ToString();
  1194. mCurTypeDef->mHash = 0xBEEF123; // Salt the hash
  1195. for (char c : fullNameStr)
  1196. mCurTypeDef->mHash = ((mCurTypeDef->mHash ^ c) << 4) - mCurTypeDef->mHash;
  1197. mCurTypeDef->mFullName = fullName;
  1198. BfTypeDef* prevRevisionTypeDef = NULL;
  1199. BfTypeDef* otherDefinitionTypeDef = NULL;
  1200. int numGenericParams = 0;
  1201. if (typeDeclaration->mGenericParams != NULL)
  1202. numGenericParams = (int)typeDeclaration->mGenericParams->mGenericParams.size();
  1203. if (outerTypeDef != NULL)
  1204. numGenericParams += (int)outerTypeDef->mGenericParamDefs.size();
  1205. if (!isAutoCompleteTempType)
  1206. {
  1207. BfTypeDef* prevDef = NULL;
  1208. // auto checkTypeDef = mSystem->mTypeDefs.Find(fullName);
  1209. // while (checkTypeDef != NULL)
  1210. auto itr = mSystem->mTypeDefs.TryGet(fullName);
  1211. while (itr)
  1212. {
  1213. BfTypeDef* checkTypeDef = *itr;
  1214. if (checkTypeDef->mDefState == BfTypeDef::DefState_Deleted)
  1215. {
  1216. itr.MoveToNextHashMatch();
  1217. continue;
  1218. }
  1219. if ((checkTypeDef->NameEquals(mCurTypeDef)) &&
  1220. (checkTypeDef->mGenericParamDefs.size() == numGenericParams) &&
  1221. (mCurTypeDef->mProject == checkTypeDef->mProject))
  1222. {
  1223. if (checkTypeDef->mIsCombinedPartial)
  1224. {
  1225. // Ignore
  1226. }
  1227. else
  1228. {
  1229. if (checkTypeDef->mDefState == BfTypeDef::DefState_AwaitingNewVersion)
  1230. {
  1231. if (isExtension == (checkTypeDef->mTypeCode == BfTypeCode_Extension))
  1232. {
  1233. if (prevRevisionTypeDef == NULL)
  1234. {
  1235. prevRevisionTypeDef = checkTypeDef;
  1236. prevDef = checkTypeDef;
  1237. }
  1238. }
  1239. }
  1240. else
  1241. {
  1242. //otherDefinitionTypeDef = prevRevisionTypeDef;
  1243. }
  1244. }
  1245. }
  1246. itr.MoveToNextHashMatch();
  1247. }
  1248. bool doInsertNew = true;
  1249. if (prevRevisionTypeDef != NULL)
  1250. {
  1251. mCurTypeDef->mIsNextRevision = true;
  1252. bfParser->mTypeDefs.Add(prevRevisionTypeDef);
  1253. if (prevRevisionTypeDef->mDefState == BfTypeDef::DefState_AwaitingNewVersion)
  1254. {
  1255. if (prevRevisionTypeDef->mNextRevision != NULL)
  1256. delete prevRevisionTypeDef->mNextRevision;
  1257. prevRevisionTypeDef->mNextRevision = mCurTypeDef;
  1258. BF_ASSERT(mCurTypeDef->mSystem != NULL);
  1259. mCurActualTypeDef = prevRevisionTypeDef;
  1260. doInsertNew = false;
  1261. }
  1262. else
  1263. {
  1264. if (prevRevisionTypeDef->mNextRevision != NULL)
  1265. prevRevisionTypeDef = prevRevisionTypeDef->mNextRevision;
  1266. prevRevisionTypeDef = NULL;
  1267. }
  1268. }
  1269. else
  1270. {
  1271. mSystem->TrackName(mCurTypeDef);
  1272. bfParser->mTypeDefs.Add(mCurTypeDef);
  1273. }
  1274. if (doInsertNew)
  1275. {
  1276. mSystem->mTypeDefs.Add(mCurTypeDef);
  1277. mSystem->mTypeMapVersion++;
  1278. }
  1279. }
  1280. else
  1281. {
  1282. mCurTypeDef->mIsNextRevision = true; // We don't track name
  1283. mResolvePassData->mAutoCompleteTempTypes.push_back(mCurTypeDef);
  1284. }
  1285. // Insert name into there
  1286. mCurTypeDef->mOuterType = actualOuterTypeDef;
  1287. //dottedName = mCurTypeDef->mName;
  1288. if ((outerTypeDef != NULL) && (!isAutoCompleteTempType))
  1289. {
  1290. outerTypeDef->mNestedTypes.push_back(mCurActualTypeDef);
  1291. }
  1292. BfLogSysM("Creating TypeDef %p from TypeDecl: %p Source: %p ResolvePass: %d\n", mCurTypeDef, typeDeclaration, typeDeclaration->GetSourceData(), mResolvePassData != NULL);
  1293. mCurTypeDef->mSource = mCurSource;
  1294. mCurTypeDef->mSource->mRefCount++;
  1295. mCurTypeDef->mTypeDeclaration = typeDeclaration;
  1296. mCurTypeDef->mIsAbstract = (typeDeclaration->mAbstractSpecifier != NULL) && (typeDeclaration->mAbstractSpecifier->GetToken() == BfToken_Abstract);
  1297. mCurTypeDef->mIsConcrete = (typeDeclaration->mAbstractSpecifier != NULL) && (typeDeclaration->mAbstractSpecifier->GetToken() == BfToken_Concrete);
  1298. mCurTypeDef->mIsStatic = typeDeclaration->mStaticSpecifier != NULL;
  1299. mCurTypeDef->mIsDelegate = false;
  1300. mCurTypeDef->mIsFunction = false;
  1301. BfToken typeToken = BfToken_None;
  1302. if (typeDeclaration->mTypeNode != NULL)
  1303. typeToken = typeDeclaration->mTypeNode->GetToken();
  1304. if (typeDeclaration->mTypeNode == NULL)
  1305. {
  1306. // Globals
  1307. mCurTypeDef->mTypeCode = BfTypeCode_Struct;
  1308. }
  1309. else if (typeToken == BfToken_Class)
  1310. {
  1311. mCurTypeDef->mTypeCode = BfTypeCode_Object;
  1312. }
  1313. else if (typeToken == BfToken_Delegate)
  1314. {
  1315. mCurTypeDef->mTypeCode = BfTypeCode_Object;
  1316. mCurTypeDef->mIsDelegate = true;
  1317. }
  1318. else if (typeToken == BfToken_Function)
  1319. {
  1320. mCurTypeDef->mTypeCode = BfTypeCode_Struct;
  1321. mCurTypeDef->mIsFunction = true;
  1322. }
  1323. else if (typeToken == BfToken_Interface)
  1324. {
  1325. mCurTypeDef->mTypeCode = BfTypeCode_Interface;
  1326. }
  1327. else if (typeToken == BfToken_Enum)
  1328. {
  1329. mCurTypeDef->mTypeCode = BfTypeCode_Enum;
  1330. }
  1331. else if (typeToken == BfToken_TypeAlias)
  1332. {
  1333. mCurTypeDef->mTypeCode = BfTypeCode_TypeAlias;
  1334. }
  1335. else if (typeToken == BfToken_Struct)
  1336. mCurTypeDef->mTypeCode = BfTypeCode_Struct;
  1337. else if (typeToken == BfToken_Extension)
  1338. mCurTypeDef->mTypeCode = BfTypeCode_Extension;
  1339. else
  1340. BF_FATAL("Unknown type token");
  1341. int outerGenericSize = 0;
  1342. if (mCurTypeDef->mOuterType != NULL)
  1343. outerGenericSize = (int)mCurTypeDef->mOuterType->mGenericParamDefs.size();
  1344. ParseGenericParams(typeDeclaration->mGenericParams, typeDeclaration->mGenericConstraintsDeclaration, mCurTypeDef->mGenericParamDefs, outerGenericSize);
  1345. BF_ASSERT(mCurTypeDef->mNameEx == NULL);
  1346. if (mCurTypeDef->mGenericParamDefs.size() != 0)
  1347. {
  1348. mCurTypeDef->mNameEx = mSystem->GetAtom(StrFormat("%s`%d", mCurTypeDef->mName->mString.mPtr, numGenericParams));
  1349. }
  1350. else
  1351. {
  1352. mCurTypeDef->mNameEx = mCurTypeDef->mName;
  1353. mCurTypeDef->mNameEx->mRefCount++;
  1354. }
  1355. if (!fullName.IsEmpty())
  1356. {
  1357. mCurTypeDef->mFullNameEx = fullName;
  1358. mCurTypeDef->mFullNameEx.mParts[mCurTypeDef->mFullNameEx.mSize - 1] = mCurTypeDef->mNameEx;
  1359. }
  1360. if (auto defineBlock = BfNodeDynCast<BfBlock>(typeDeclaration->mDefineNode))
  1361. {
  1362. for (auto& member : *defineBlock)
  1363. {
  1364. VisitChildNoRef(member);
  1365. }
  1366. }
  1367. else if (auto defineTokenNode = BfNodeDynCast<BfTokenNode>(typeDeclaration->mDefineNode))
  1368. {
  1369. if (defineTokenNode->GetToken() == BfToken_Semicolon)
  1370. {
  1371. mCurTypeDef->mIsOpaque = true;
  1372. }
  1373. }
  1374. FinishTypeDef(mCurTypeDef->mTypeCode == BfTypeCode_Enum);
  1375. // Map methods into the correct index from previous revision
  1376. if (prevRevisionTypeDef != NULL)
  1377. {
  1378. if ((mCurTypeDef->mFullHash == prevRevisionTypeDef->mFullHash) && (!mFullRefresh))
  1379. {
  1380. BfLogSys(bfParser->mSystem, "DefBuilder deleting typeDef with no changes %p\n", prevRevisionTypeDef);
  1381. prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Defined;
  1382. BF_ASSERT(prevRevisionTypeDef->mNextRevision == mCurTypeDef);
  1383. prevRevisionTypeDef->mNextRevision = NULL;
  1384. delete mCurTypeDef;
  1385. mCurTypeDef = NULL;
  1386. }
  1387. else if (mCurTypeDef->mSignatureHash != prevRevisionTypeDef->mSignatureHash)
  1388. prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Signature_Changed;
  1389. else if (mCurTypeDef->mInlineHash != prevRevisionTypeDef->mInlineHash)
  1390. prevRevisionTypeDef->mDefState = BfTypeDef::DefState_InlinedInternals_Changed;
  1391. else
  1392. prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Internals_Changed;
  1393. }
  1394. // There's a new type with this name...
  1395. if ((prevRevisionTypeDef == NULL) && (!isAutoCompleteTempType))
  1396. {
  1397. mCurTypeDef->mName->mAtomUpdateIdx = ++mSystem->mAtomUpdateIdx;
  1398. }
  1399. mCurTypeDef = outerTypeDef;
  1400. mCurActualTypeDef = actualOuterTypeDef;
  1401. }
  1402. void BfDefBuilder::FinishTypeDef(bool wantsToString)
  1403. {
  1404. auto bfSource = mCurTypeDef->mSource;
  1405. bool isAlias = mCurTypeDef->mTypeCode == BfTypeCode_TypeAlias;
  1406. bool hasCtor = false;
  1407. bool needsDefaultCtor = (mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (!mCurTypeDef->mIsStatic) && (!isAlias);
  1408. bool hasDefaultCtor = false;
  1409. bool hasStaticCtor = false;
  1410. bool hasDtor = false;
  1411. bool hasStaticDtor = false;
  1412. bool hasMarkMethod = false;
  1413. bool hasStaticMarkMethod = false;
  1414. bool hasDynamicCastMethod = false;
  1415. bool hasToStringMethod = false;
  1416. bool needsEqualsMethod = ((mCurTypeDef->mTypeCode == BfTypeCode_Struct) || (mCurTypeDef->mTypeCode == BfTypeCode_Enum)) && (!mCurTypeDef->mIsStatic);
  1417. bool hasEqualsMethod = false;
  1418. bool needsStaticInit = false;
  1419. for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++)
  1420. {
  1421. auto method = mCurTypeDef->mMethods[methodIdx];
  1422. if (method->mMethodType == BfMethodType_Ctor)
  1423. {
  1424. if (method->mIsStatic)
  1425. {
  1426. if (hasStaticCtor)
  1427. {
  1428. mPassInstance->Fail("Only one static constructor is allowed", method->mMethodDeclaration);
  1429. method->mIsStatic = false;
  1430. }
  1431. if (method->mParams.size() != 0)
  1432. {
  1433. mPassInstance->Fail("Static constructor cannot declare parameters", method->mMethodDeclaration);
  1434. method->mIsStatic = false;
  1435. }
  1436. if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC)
  1437. hasStaticMarkMethod = true;
  1438. hasStaticCtor = true;
  1439. }
  1440. else
  1441. {
  1442. hasCtor = true;
  1443. if (method->mParams.size() == 0)
  1444. hasDefaultCtor = true;
  1445. auto ctorDeclaration = (BfConstructorDeclaration*)method->mMethodDeclaration;
  1446. if (method->mHasAppend)
  1447. {
  1448. mCurTypeDef->mHasAppendCtor = true;
  1449. auto methodDef = new BfMethodDef();
  1450. mCurTypeDef->mMethods.Insert(methodIdx + 1, methodDef);
  1451. methodDef->mDeclaringType = mCurTypeDef;
  1452. methodDef->mName = BF_METHODNAME_CALCAPPEND;
  1453. methodDef->mProtection = BfProtection_Public;
  1454. methodDef->mMethodType = BfMethodType_CtorCalcAppend;
  1455. methodDef->mIsMutating = method->mIsMutating;
  1456. methodDef->mMethodDeclaration = method->mMethodDeclaration;
  1457. methodDef->mReturnTypeRef = mSystem->mDirectIntTypeRef;
  1458. methodDef->mIsStatic = true;
  1459. methodDef->mBody = method->mBody;
  1460. for (auto param : method->mParams)
  1461. {
  1462. BfParameterDef* newParam = new BfParameterDef();
  1463. newParam->mName = param->mName;
  1464. newParam->mTypeRef = param->mTypeRef;
  1465. newParam->mMethodGenericParamIdx = param->mMethodGenericParamIdx;
  1466. methodDef->mParams.push_back(newParam);
  1467. }
  1468. // Insert a 'appendIdx'
  1469. BfParameterDef* newParam = new BfParameterDef();
  1470. newParam->mName = "appendIdx";
  1471. newParam->mTypeRef = mSystem->mDirectRefIntTypeRef;
  1472. newParam->mParamKind = BfParamKind_AppendIdx;
  1473. method->mParams.Insert(0, newParam);
  1474. }
  1475. }
  1476. }
  1477. else if (method->mMethodType == BfMethodType_Dtor)
  1478. {
  1479. if (method->mIsStatic)
  1480. {
  1481. if (hasStaticDtor)
  1482. {
  1483. mPassInstance->Fail("Only one static constructor is allowed", method->mMethodDeclaration);
  1484. method->mIsStatic = false;
  1485. }
  1486. hasStaticDtor = true;
  1487. }
  1488. else
  1489. {
  1490. if (hasDtor)
  1491. {
  1492. mPassInstance->Fail("Only one destructor is allowed", method->mMethodDeclaration);
  1493. method->mIsStatic = false;
  1494. }
  1495. hasDtor = true;
  1496. }
  1497. if (method->mParams.size() != 0)
  1498. mPassInstance->Fail("Destructors cannot declare parameters", method->GetMethodDeclaration()->mParams[0]);
  1499. }
  1500. else if (method->mMethodType == BfMethodType_Normal)
  1501. {
  1502. if (method->mIsStatic)
  1503. {
  1504. if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC)
  1505. hasStaticMarkMethod = true;
  1506. }
  1507. else
  1508. {
  1509. if (method->mName == BF_METHODNAME_MARKMEMBERS)
  1510. hasMarkMethod = true;
  1511. if (method->mName == BF_METHODNAME_DYNAMICCAST)
  1512. hasDynamicCastMethod = true;
  1513. if (method->mName == BF_METHODNAME_TO_STRING)
  1514. hasToStringMethod = true;
  1515. }
  1516. }
  1517. else if ((method->mMethodType == BfMethodType_Operator) &&
  1518. (method->mIsStatic) &&
  1519. (method->mParams.size() == 2))
  1520. {
  1521. if (auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(method->mMethodDeclaration))
  1522. {
  1523. if (operatorDecl->mBinOp == BfBinaryOp_Equality)
  1524. {
  1525. // This is a conservative check. It's okay to add a system-defined equals method even if we don't need it.
  1526. if ((method->mParams[0]->mTypeRef->ToString() == mCurTypeDef->mName->ToString()) &&
  1527. (method->mParams[1]->mTypeRef->ToString() == mCurTypeDef->mName->ToString()))
  1528. {
  1529. hasEqualsMethod = true;
  1530. }
  1531. }
  1532. }
  1533. }
  1534. if (method->mImportKind == BfImportKind_Dynamic)
  1535. needsStaticInit = true;
  1536. }
  1537. if (mCurTypeDef->IsExtension())
  1538. needsDefaultCtor = false;
  1539. bool needsDtor = false;
  1540. bool needsStaticDtor = false;
  1541. bool hasStaticField = false;
  1542. bool hasNonStaticField = false;
  1543. bool hasThreadStatics = false;
  1544. for (auto field : mCurTypeDef->mFields)
  1545. {
  1546. if (field->mIsStatic)
  1547. {
  1548. // Resolve-only compiler wants to visit const initializers in a static ctor method, but we don't
  1549. // want to create it for the actual binary
  1550. if ((!field->mIsConst) || (mSystem->mIsResolveOnly))
  1551. {
  1552. hasStaticField = true;
  1553. if (field->mFieldDeclaration != NULL)
  1554. {
  1555. if (field->mFieldDeclaration->mInitializer != NULL)
  1556. {
  1557. needsStaticInit = true;
  1558. }
  1559. if (field->mFieldDeclaration->mFieldDtor != NULL)
  1560. needsStaticDtor = true;
  1561. }
  1562. }
  1563. if (field->mFieldDeclaration != NULL)
  1564. {
  1565. auto attributes = field->mFieldDeclaration->mAttributes;
  1566. while (attributes != NULL)
  1567. {
  1568. if (attributes->mAttributeTypeRef != NULL)
  1569. {
  1570. auto typeRefName = attributes->mAttributeTypeRef->ToString();
  1571. if (typeRefName == "ThreadStatic")
  1572. hasThreadStatics = true;
  1573. }
  1574. attributes = attributes->mNextAttribute;
  1575. }
  1576. }
  1577. }
  1578. else
  1579. {
  1580. hasNonStaticField = true;
  1581. if (field->mInitializer != NULL)
  1582. needsDefaultCtor = true;
  1583. if ((field->mFieldDeclaration != NULL) && (field->mFieldDeclaration->mFieldDtor != NULL))
  1584. needsDtor = true;
  1585. }
  1586. }
  1587. if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic))
  1588. {
  1589. auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, "");
  1590. methodDef->mIsMutating = true;
  1591. }
  1592. if ((needsDtor) && (!hasDtor))
  1593. {
  1594. auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, false, "");
  1595. BF_ASSERT(mCurTypeDef->mDtorDef == methodDef);
  1596. }
  1597. if ((needsStaticDtor) && (!hasStaticDtor))
  1598. {
  1599. auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, true, "");
  1600. }
  1601. if ((needsStaticInit) && (!hasStaticCtor))
  1602. {
  1603. auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, BfProtection_Public, true, "");
  1604. }
  1605. bool makeCtorPrivate = hasCtor;
  1606. // if ((!mCurTypeDef->IsExtension()) && (mCurTypeDef->mMethods.empty()))
  1607. // {
  1608. // // This is a bit of a hack to ensure we actually generate debug info in the module
  1609. // needsDefaultCtor = true;
  1610. // makeCtorPrivate = true;
  1611. // }
  1612. if (mCurTypeDef->mTypeCode == BfTypeCode_TypeAlias)
  1613. needsDefaultCtor = false;
  1614. if ((needsDefaultCtor) && (!hasDefaultCtor))
  1615. {
  1616. // Create default constructor. If it's the only constructor then make it public,
  1617. // otherwise make it private so we can still internally use it but the user can't
  1618. auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, hasCtor ? BfProtection_Private : BfProtection_Public, false, "");
  1619. methodDef->mIsMutating = true;
  1620. }
  1621. bool isAutocomplete = false;
  1622. if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
  1623. isAutocomplete = true;
  1624. //TODO: Don't do this for the autocomplete pass
  1625. if ((!hasDynamicCastMethod) && (mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (mCurTypeDef->mTypeCode != BfTypeCode_Extension) &&
  1626. (!mCurTypeDef->mIsStatic) && (!isAutocomplete) && (!isAlias))
  1627. {
  1628. AddDynamicCastMethods(mCurTypeDef);
  1629. }
  1630. bool isPayloadEnum = false;
  1631. if (mCurTypeDef->mTypeCode == BfTypeCode_Enum)
  1632. {
  1633. for (auto fieldDef : mCurTypeDef->mFields)
  1634. {
  1635. if (auto enumEntryDecl = BfNodeDynCast<BfEnumEntryDeclaration>(fieldDef->mFieldDeclaration))
  1636. {
  1637. if (enumEntryDecl->mTypeRef != NULL)
  1638. isPayloadEnum = true;
  1639. }
  1640. }
  1641. }
  1642. if (isPayloadEnum)
  1643. hasNonStaticField = true;
  1644. if (mCurTypeDef->mTypeCode != BfTypeCode_Interface)
  1645. {
  1646. if ((hasStaticField) && (!hasStaticMarkMethod))
  1647. {
  1648. auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_MARKMEMBERS_STATIC);
  1649. methodDef->mNoReflect = true;
  1650. }
  1651. if (hasThreadStatics)
  1652. {
  1653. auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_FIND_TLS_MEMBERS);
  1654. methodDef->mNoReflect = true;
  1655. }
  1656. if ((hasNonStaticField) && (!hasMarkMethod))
  1657. {
  1658. auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, false, BF_METHODNAME_MARKMEMBERS);
  1659. methodDef->mIsVirtual = true;
  1660. methodDef->mIsOverride = true;
  1661. methodDef->mNoReflect = true;
  1662. methodDef->mNoSplat = true;
  1663. mCurTypeDef->mHasOverrideMethods = true;
  1664. }
  1665. }
  1666. if (hasToStringMethod)
  1667. wantsToString = false;
  1668. if (mCurTypeDef->mIsFunction)
  1669. {
  1670. wantsToString = false;
  1671. needsEqualsMethod = false;
  1672. }
  1673. if ((mCurTypeDef->mTypeCode == BfTypeCode_Enum) && (!isPayloadEnum))
  1674. {
  1675. auto methodDef = new BfMethodDef();
  1676. mCurTypeDef->mMethods.push_back(methodDef);
  1677. methodDef->mDeclaringType = mCurTypeDef;
  1678. methodDef->mName = BF_METHODNAME_ENUM_HASFLAG;
  1679. methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef;
  1680. methodDef->mProtection = BfProtection_Public;
  1681. AddParam(methodDef, mSystem->mDirectSelfTypeRef, "checkEnum");
  1682. // Underlying
  1683. {
  1684. auto methodDef = new BfMethodDef();
  1685. mCurTypeDef->mMethods.push_back(methodDef);
  1686. methodDef->mDeclaringType = mCurTypeDef;
  1687. methodDef->mName = BF_METHODNAME_ENUM_GETUNDERLYING;
  1688. methodDef->mReturnTypeRef = mSystem->mDirectSelfBaseTypeRef;
  1689. methodDef->mMethodType = BfMethodType_PropertyGetter;
  1690. methodDef->mProtection = BfProtection_Public;
  1691. auto propDef = new BfPropertyDef();
  1692. mCurTypeDef->mProperties.Add(propDef);
  1693. propDef->mTypeRef = mSystem->mDirectSelfBaseTypeRef;
  1694. propDef->mDeclaringType = mCurTypeDef;
  1695. propDef->mName = "Underlying";
  1696. propDef->mMethods.Add(methodDef);
  1697. propDef->mProtection = BfProtection_Public;
  1698. }
  1699. // UnderlyingRef
  1700. {
  1701. auto methodDef = new BfMethodDef();
  1702. mCurTypeDef->mMethods.push_back(methodDef);
  1703. methodDef->mDeclaringType = mCurTypeDef;
  1704. methodDef->mIsMutating = true;
  1705. methodDef->mName = BF_METHODNAME_ENUM_GETUNDERLYINGREF;
  1706. methodDef->mReturnTypeRef = mSystem->mDirectRefSelfBaseTypeRef;
  1707. methodDef->mMethodType = BfMethodType_PropertyGetter;
  1708. methodDef->mProtection = BfProtection_Public;
  1709. auto propDef = new BfPropertyDef();
  1710. mCurTypeDef->mProperties.Add(propDef);
  1711. propDef->mTypeRef = mSystem->mDirectRefSelfBaseTypeRef;
  1712. propDef->mDeclaringType = mCurTypeDef;
  1713. propDef->mName = "UnderlyingRef";
  1714. propDef->mMethods.Add(methodDef);
  1715. propDef->mProtection = BfProtection_Public;
  1716. }
  1717. }
  1718. if (wantsToString)
  1719. {
  1720. auto methodDef = new BfMethodDef();
  1721. mCurTypeDef->mMethods.push_back(methodDef);
  1722. methodDef->mDeclaringType = mCurTypeDef;
  1723. methodDef->mName = BF_METHODNAME_TO_STRING;
  1724. methodDef->mReturnTypeRef = mSystem->mDirectVoidTypeRef;
  1725. methodDef->mProtection = BfProtection_Public;
  1726. methodDef->mIsOverride = true;
  1727. methodDef->mIsVirtual = true;
  1728. AddParam(methodDef, mSystem->mDirectStringTypeRef, "outStr");
  1729. mCurTypeDef->mHasOverrideMethods = true;
  1730. }
  1731. if ((needsEqualsMethod) && (!hasEqualsMethod))
  1732. {
  1733. auto methodDef = new BfMethodDef();
  1734. mCurTypeDef->mMethods.push_back(methodDef);
  1735. methodDef->mDeclaringType = mCurTypeDef;
  1736. methodDef->mName = BF_METHODNAME_DEFAULT_EQUALS;
  1737. methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef;
  1738. methodDef->mProtection = BfProtection_Private;
  1739. methodDef->mIsStatic = true;
  1740. AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs");
  1741. AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs");
  1742. }
  1743. HashContext inlineHashCtx;
  1744. //for (auto methodDef : mCurTypeDef->mMethods)
  1745. for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++)
  1746. {
  1747. // Add in name so the hand-created methods can be compared by hash
  1748. auto methodDef = mCurTypeDef->mMethods[methodIdx];
  1749. methodDef->mIdx = methodIdx;
  1750. methodDef->mFullHash = HashString(methodDef->mName, methodDef->mFullHash);
  1751. if (mSignatureHashCtx != NULL)
  1752. mSignatureHashCtx->MixinStr(methodDef->mName);
  1753. if ((methodDef->mAlwaysInline) ||
  1754. (methodDef->mHasAppend) ||
  1755. (methodDef->mMethodType == BfMethodType_Mixin))
  1756. inlineHashCtx.Mixin(methodDef->mFullHash);
  1757. if (mFullRefresh)
  1758. methodDef->mCodeChanged = true;
  1759. }
  1760. mCurTypeDef->mInlineHash = inlineHashCtx.Finish128();
  1761. if (mSignatureHashCtx != NULL)
  1762. {
  1763. mCurTypeDef->mSignatureHash = mSignatureHashCtx->Finish128();
  1764. // We need to hash the signature in here because the preprocessor settings
  1765. // may change so the text is the same but the signature changes
  1766. // so fullHash needs to change too
  1767. mFullHashCtx->Mixin(mCurTypeDef->mSignatureHash);
  1768. }
  1769. if (mFullHashCtx != NULL)
  1770. mCurTypeDef->mFullHash = mFullHashCtx->Finish128();
  1771. }
  1772. void BfDefBuilder::Visit(BfUsingDirective* usingDirective)
  1773. {
  1774. if (usingDirective->mNamespace == NULL)
  1775. {
  1776. BF_ASSERT(mPassInstance->HasFailed());
  1777. return;
  1778. }
  1779. if (mResolvePassData != NULL)
  1780. mResolvePassData->mExteriorAutocompleteCheckNodes.push_back(usingDirective);
  1781. String usingString = usingDirective->mNamespace->ToString();
  1782. BfAtomComposite usingComposite;
  1783. mSystem->ParseAtomComposite(usingString, usingComposite, true);
  1784. if (!mNamespaceSearch.Contains(usingComposite))
  1785. mNamespaceSearch.Insert(0, usingComposite);
  1786. else
  1787. mSystem->ReleaseAtomComposite(usingComposite);
  1788. }
  1789. void BfDefBuilder::Visit(BfUsingStaticDirective* usingDirective)
  1790. {
  1791. if (mResolvePassData != NULL)
  1792. mResolvePassData->mExteriorAutocompleteCheckNodes.push_back(usingDirective);
  1793. if (usingDirective->mTypeRef != NULL)
  1794. mStaticSearch.Add(usingDirective->mTypeRef);
  1795. }
  1796. void BfDefBuilder::Visit(BfNamespaceDeclaration* namespaceDeclaration)
  1797. {
  1798. BfAtomComposite prevNamespace = mNamespace;
  1799. int prevNamespaceSearchCount = (int)mNamespaceSearch.size();
  1800. if (namespaceDeclaration->mNameNode == NULL)
  1801. return;
  1802. String namespaceLeft = namespaceDeclaration->mNameNode->ToString();
  1803. while (true)
  1804. {
  1805. int dotIdx = (int)namespaceLeft.IndexOf('.');
  1806. if (dotIdx == -1)
  1807. {
  1808. BfAtom* namespaceAtom = mSystem->GetAtom(namespaceLeft);
  1809. mNamespace.Set(mNamespace.mParts, mNamespace.mSize, &namespaceAtom, 1);
  1810. if (!mNamespaceSearch.Contains(mNamespace))
  1811. {
  1812. mSystem->RefAtomComposite(mNamespace);
  1813. mNamespaceSearch.Insert(0, mNamespace);
  1814. }
  1815. mSystem->ReleaseAtom(namespaceAtom);
  1816. break;
  1817. }
  1818. BfAtom* namespaceAtom = mSystem->GetAtom(namespaceLeft.Substring(0, dotIdx));
  1819. mNamespace.Set(mNamespace.mParts, mNamespace.mSize, &namespaceAtom, 1);
  1820. namespaceLeft = namespaceLeft.Substring(dotIdx + 1);
  1821. if (!mNamespaceSearch.Contains(mNamespace))
  1822. {
  1823. mSystem->RefAtomComposite(mNamespace);
  1824. mNamespaceSearch.Insert(0, mNamespace);
  1825. }
  1826. mSystem->ReleaseAtom(namespaceAtom);
  1827. }
  1828. VisitChild(namespaceDeclaration->mBlock);
  1829. while ((int)mNamespaceSearch.size() > prevNamespaceSearchCount)
  1830. {
  1831. BfAtomComposite& atomComposite = mNamespaceSearch[0];
  1832. mSystem->ReleaseAtomComposite(atomComposite);
  1833. mNamespaceSearch.RemoveAt(0);
  1834. }
  1835. mNamespace = prevNamespace;
  1836. }
  1837. void BfDefBuilder::Visit(BfBlock* block)
  1838. {
  1839. VisitMembers(block);
  1840. }
  1841. void BfDefBuilder::Visit(BfRootNode* rootNode)
  1842. {
  1843. VisitMembers(rootNode);
  1844. }