PageRenderTime 69ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/pinot/src/control.cpp

https://bitbucket.org/gkakaron/copeswingapp
C++ | 7818 lines | 6475 code | 589 blank | 754 comment | 2184 complexity | 75f0d08c41dc9dbf8392b8cc776ddda0 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. // $Id: control.cpp,v 1.88 2006/03/15 06:19:48 shini Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://ibm.com/developerworks/opensource/jikes.
  6. // Copyright (C) 1996, 2004 IBM Corporation and others. All Rights Reserved.
  7. // You must accept the terms of that agreement to use this software.
  8. //
  9. #include "control.h"
  10. #include "scanner.h"
  11. #include "parser.h"
  12. #include "semantic.h"
  13. #include "error.h"
  14. #include "bytecode.h"
  15. #include "case.h"
  16. #include "option.h"
  17. #include <fstream>
  18. #include <iomanip>
  19. #include <dlfcn.h>
  20. #include <stdlib.h>
  21. #ifdef HAVE_JIKES_NAMESPACE
  22. namespace Jikes { // Open namespace Jikes block
  23. #endif
  24. int counter1, counter2, counter3;
  25. int nSingleton, nCoR, nBridge, nStrategy, nState, nFlyweight, nComposite, nMediator, nTemplate, nFactoryMethod, nAbstractFactory, nVisitor, nDecorator, nObserver, nProxy, nAdapter, nFacade;
  26. bool PINOT_DEBUG;
  27. SymbolSet mediators;
  28. int nMediatorFacadeDual = 0, nFlyweightGoFVersion = 0, nImmutable = 0;
  29. /**
  30. * Utility functions
  31. */
  32. ContainerType *Utility::IdentifyContainerType(VariableSymbol *vsym)
  33. {
  34. TypeSymbol *type = vsym->Type();
  35. if (type->Primitive())
  36. return NULL;
  37. if (type->IsArray())
  38. // can be 2D, 3D, etc.
  39. return new ArrayContainer(vsym);
  40. if (strcmp(type->fully_qualified_name->value, "java/util/Vector") == 0)
  41. return new VectorContainer(vsym);
  42. else if (strcmp(type->fully_qualified_name->value, "java/util/ArrayList") == 0)
  43. return new ArrayListContainer(vsym);
  44. else if (strcmp(type->fully_qualified_name->value, "java/util/LinkedList") == 0)
  45. return new ArrayListContainer(vsym);
  46. if (type->supertypes_closure)
  47. {
  48. Symbol *sym= type->supertypes_closure->FirstElement();
  49. while(sym)
  50. {
  51. if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/util/Map") == 0)
  52. return new MapContainer(vsym);
  53. else if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/util/Collection") == 0)
  54. return new CollectionContainer(vsym);
  55. sym = type->supertypes_closure->NextElement();
  56. }
  57. }
  58. return NULL;
  59. }
  60. void Utility::RemoveJavaBaseClass(SymbolSet& set)
  61. {
  62. Symbol *sym = set.FirstElement();
  63. while(sym)
  64. {
  65. if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/lang/Object") == 0)
  66. {
  67. set.RemoveElement(sym);
  68. break;
  69. }
  70. sym = set.NextElement();
  71. }
  72. }
  73. void Utility::RemoveBuiltinInterfaces(SymbolSet& set)
  74. {
  75. SymbolSet temp;
  76. Symbol *sym = set.FirstElement();
  77. while(sym)
  78. {
  79. if (sym->TypeCast()->file_symbol->IsJava())
  80. temp.AddElement(sym);
  81. sym = set.NextElement();
  82. }
  83. set.Intersection(temp);
  84. }
  85. TypeSymbol *Utility::GetTypeSymbol(Symbol *sym)
  86. {
  87. if (sym->Kind() == Symbol::TYPE)
  88. return sym->TypeCast();
  89. else if (sym->Kind() == Symbol::VARIABLE)
  90. return sym->VariableCast()->Type();
  91. else if (sym->Kind() == Symbol::METHOD)
  92. return sym->MethodCast()->Type();
  93. else
  94. return NULL;
  95. }
  96. AstExpression *Utility::RemoveCasting(AstExpression *expr)
  97. {
  98. if (expr->kind == Ast::CAST)
  99. return RemoveCasting(expr->CastExpressionCast()->expression);
  100. else if (expr->kind == Ast::PARENTHESIZED_EXPRESSION)
  101. return RemoveCasting(expr->ParenthesizedExpressionCast()->expression);
  102. else
  103. return expr;
  104. }
  105. void Utility::Intersection(vector<signed>& a, vector<signed>& b, vector<signed>& c)
  106. {
  107. for (unsigned i = 0; i < a.size(); i++)
  108. for (unsigned j = 0; j < b.size(); j++)
  109. if (a[i] == b[j])
  110. c.push_back(a[i]);
  111. }
  112. void Utility::RemoveDuplicates(vector<signed>& a)
  113. {
  114. vector<signed> b;
  115. for (unsigned i = 0; i < a.size(); i++)
  116. {
  117. unsigned j = 0;
  118. while ((j < b.size()) && (a[i] != b[j])) j++;
  119. if (j == b.size())
  120. b.push_back(a[i]);
  121. }
  122. a.swap(b);
  123. }
  124. bool Utility::Aliasing(VariableSymbol *v1, VariableSymbol *v2)
  125. {
  126. if (!v1->aliases)
  127. return false;
  128. else if (v1->aliases->IsElement(v2))
  129. return true;
  130. else
  131. {
  132. Symbol *sym = v1->aliases->FirstElement();
  133. while(sym)
  134. {
  135. // reach two-hops only
  136. if (sym->VariableCast()->aliases && sym->VariableCast()->aliases->IsElement(v2))
  137. return true;
  138. sym = v1->aliases->NextElement();
  139. }
  140. return false;
  141. }
  142. }
  143. bool isCached(wchar_t* name, vector<wchar_t*>* cache)
  144. {
  145. bool flag = false;
  146. if (cache)
  147. {
  148. unsigned i = 0;
  149. while ((!flag) && (i < cache -> size()))
  150. {
  151. if (wcscmp((*cache)[i], name) == 0)
  152. flag = true;
  153. else
  154. i++;
  155. }
  156. }
  157. return flag;
  158. }
  159. bool intersection(vector<wchar_t*>* list1, vector<wchar_t*>* list2)
  160. {
  161. bool flag = false;
  162. if (list1 && list2)
  163. {
  164. unsigned i = 0, j;
  165. while (!flag && (i < list1 -> size()))
  166. {
  167. j = 0;
  168. while (!flag && (j < list2 -> size()))
  169. {
  170. if (wcscmp((*list1)[i], (*list2)[j]) == 0)
  171. flag = true;
  172. else
  173. j++;
  174. }
  175. if (!flag)
  176. i++;
  177. }
  178. }
  179. return flag;
  180. }
  181. void printVector(vector<wchar_t*>* v)
  182. {
  183. if (v)
  184. {
  185. unsigned i;
  186. for (i = 0; i < v -> size(); i++)
  187. {
  188. if (i > 0)
  189. Coutput << " ";
  190. Coutput << (*v)[i];
  191. }
  192. Coutput << endl;
  193. }
  194. }
  195. /**
  196. * GoF patterns
  197. */
  198. void PrintSingletonXMI(TypeSymbol *class_sym , VariableSymbol *instance_sym, MethodSymbol *method_sym);
  199. void FindPrototype(MethodBodyTable* mb_table, GenTable* gen_table, AssocTable* assoc_table)
  200. {
  201. vector<wchar_t*>* prototypes = NULL;
  202. prototypes = gen_table -> getSuccessors(L"Cloneable", GenTable::IMPL);
  203. if (prototypes)
  204. {
  205. unsigned i;
  206. for (i = 0; i < prototypes -> size(); i++)
  207. {
  208. int j;
  209. for (j = 0; j < assoc_table -> getSize(); j++)
  210. {
  211. if ((assoc_table -> getKindAt(j) == Assoc::MR)
  212. && (wcscmp(assoc_table -> getTypeAt(j), (*prototypes)[i]) == 0))
  213. {
  214. wchar_t* factory = assoc_table -> getClassNameAt(j);
  215. wchar_t* method_name = assoc_table -> getMethodNameAt(j);
  216. wchar_t* var_name = assoc_table -> getName(Assoc::CF, Assoc::PRIVATE, (*prototypes)[i], factory);
  217. AstMethodDeclaration* method_declaration = dynamic_cast<AstMethodDeclaration*>(mb_table -> getAstLocation(factory, method_name));
  218. AstMethodBody* method_body = method_declaration -> method_body_opt;
  219. Coutput << L"Prototype Factory: " << factory << endl
  220. << L"Make Method: " << method_name << endl
  221. << L"Prototype Var: " << var_name <<endl << endl;
  222. Coutput << L"AST of " << method_name << endl;
  223. method_body -> Print();
  224. if ((method_body -> NumStatements() == 1)
  225. && (method_body -> Statement(0) -> kind == Ast::RETURN))
  226. {
  227. AstReturnStatement* return_statement = dynamic_cast<AstReturnStatement*>(method_body -> Statement(0));
  228. if (return_statement -> expression_opt -> kind == Ast::CAST)
  229. {
  230. AstCastExpression* cast_expression = dynamic_cast<AstCastExpression*>(return_statement -> expression_opt);
  231. AstMethodInvocation* method_invocation = dynamic_cast<AstMethodInvocation*>(cast_expression -> expression);
  232. if ((wcscmp(method_invocation -> identifier_token_string, L"clone") == 0)
  233. && (wcscmp(dynamic_cast<AstName*>(method_invocation -> base_opt) -> identifier_token_string, var_name) == 0))
  234. Coutput << L"Yoohoo" << endl;
  235. }
  236. }
  237. Coutput << endl << endl;
  238. }
  239. }
  240. }
  241. }
  242. }
  243. void FindSingleton1(ClassSymbolTable *cs_table, StoragePool *ast_pool)
  244. {
  245. if (PINOT_DEBUG)
  246. Coutput << "Identifying the Singleton Pattern" << endl;
  247. for (unsigned c = 0; c < cs_table -> size(); c++)
  248. {
  249. TypeSymbol *unit_type = (*cs_table)[c];
  250. if (PINOT_DEBUG)
  251. Coutput << "Analyzing class: " << unit_type->fully_qualified_name->value << endl;
  252. //if (unit_type->Anonymous()) break;
  253. bool instantiable = true; //for Singleton pattern, either class is abtract or ctor is private
  254. VariableSymbol *instance = NULL;
  255. MethodSymbol *GetInstance = NULL;
  256. if (unit_type -> ACC_ABSTRACT())
  257. instantiable = false;
  258. for (unsigned i = 0; i < unit_type->NumVariableSymbols(); i++)
  259. {
  260. VariableSymbol *vsym = unit_type->VariableSym(i);
  261. if (vsym->ACC_PRIVATE() && vsym->ACC_STATIC() && (vsym->Type() == unit_type))
  262. {
  263. instance = vsym;
  264. break;
  265. }
  266. }
  267. for (unsigned i = 0; (instantiable || !GetInstance) && (i < unit_type->NumMethodSymbols()); i++)
  268. {
  269. MethodSymbol *msym = unit_type->MethodSym(i);
  270. if (msym->declaration)
  271. {
  272. if (msym->declaration->kind == Ast::CONSTRUCTOR)
  273. {
  274. if (msym->ACC_PRIVATE())
  275. instantiable = false;
  276. }
  277. else if (msym->declaration->kind == Ast::METHOD)
  278. {
  279. if (msym->ACC_PUBLIC() && msym->ACC_STATIC() && (msym->Type() == unit_type))
  280. GetInstance = msym;
  281. }
  282. }
  283. }
  284. if (!instantiable && instance && GetInstance)
  285. {
  286. // Do the behavioral analysis
  287. SingletonAnalysis singleton(instance, GetInstance, ast_pool);
  288. //Coutput << unit_type->file_symbol->FileName() << endl;
  289. if (singleton.ReturnsSingleton())
  290. {
  291. Coutput << ((GetInstance-> ACC_SYNCHRONIZED()) ? "" : "") << "Singleton Pattern." << endl
  292. << unit_type->Utf8Name() << " is a Singleton class" << endl
  293. << instance->Utf8Name() << " is the Singleton instance" << endl
  294. << GetInstance->Utf8Name() << " creates and returns " << instance->Utf8Name() << endl
  295. << "File location: " << unit_type->file_symbol->FileName() << endl
  296. << ((GetInstance->ACC_SYNCHRONIZED()) ? "Double-checked Locking not used.\n" : "\n") << endl;
  297. nSingleton++;
  298. }
  299. singleton.CleanUp();
  300. }
  301. }
  302. }
  303. void FindSingleton(ClassSymbolTable *cs_table, MethodSymbolTable* ms_table)
  304. {
  305. vector<TypeSymbol*> candidates_t;
  306. for (unsigned i = 0; i<ms_table->size(); i++)
  307. {
  308. MethodSymbol *method = (*ms_table)[i];
  309. if (method -> declaration -> kind == Ast::CONSTRUCTOR)
  310. {
  311. if (method -> ACC_PRIVATE())
  312. {
  313. TypeSymbol *unit_type = method -> containing_type;
  314. candidates_t.push_back(unit_type);
  315. }
  316. }
  317. }
  318. unsigned c;
  319. for (c = 0; c < cs_table -> size(); c++)
  320. {
  321. TypeSymbol *unit_type = (*cs_table)[c];
  322. if (unit_type -> ACC_ABSTRACT())
  323. {
  324. candidates_t.push_back(unit_type);
  325. }
  326. }
  327. if (candidates_t.size() > 0)
  328. {
  329. unsigned i;
  330. for (i = 0; i < candidates_t.size(); i++)
  331. {
  332. AstClassBody *class_body = candidates_t[i] -> declaration;
  333. // find the class variable
  334. VariableSymbol *instance_sym = NULL;
  335. for (unsigned j = 0; !instance_sym && (j < class_body -> NumClassVariables()); j++)
  336. {
  337. AstFieldDeclaration* field_decl = class_body -> ClassVariable(j);
  338. TypeSymbol *type = field_decl -> type -> symbol;
  339. if ((type == candidates_t[i]) && (field_decl -> NumVariableDeclarators() == 1))
  340. {
  341. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(0);
  342. if (vd -> symbol -> ACC_PRIVATE())
  343. instance_sym = vd -> symbol;
  344. }
  345. }
  346. // find the get_instance method
  347. MethodSymbol *get_method_sym = NULL;
  348. for (unsigned j = 0; !get_method_sym && (j < class_body -> NumMethods()); j++)
  349. {
  350. AstMethodDeclaration* method = class_body -> Method(j);
  351. if ((method -> method_symbol)
  352. && (method -> method_symbol -> Type() == candidates_t[i])
  353. && (method -> method_symbol -> ACC_STATIC())
  354. && (method -> method_symbol -> ACC_PUBLIC()))
  355. get_method_sym = method -> method_symbol;
  356. }
  357. if (instance_sym && get_method_sym)
  358. {
  359. AstMethodDeclaration *method_declaration = get_method_sym -> declaration -> MethodDeclarationCast();
  360. AstMethodBody *method_body = method_declaration -> method_body_opt;
  361. wchar_t *instance_name = const_cast<wchar_t*>(instance_sym -> Name());
  362. if (method_body -> returnsVar(instance_name))
  363. {
  364. EnvTable *env = new EnvTable();
  365. env -> addEnvironment(instance_name, Env::INIT);
  366. method_body -> simulate(env);
  367. if (env -> getState(instance_name) == Env::INIT)
  368. {
  369. /*
  370. char* file_name = method_sym -> containing_type -> file_symbol -> FileName();
  371. TypeSymbol *class_sym = NULL;
  372. for (unsigned i = 0; !class_sym && (i < candidates_t.size()); i++)
  373. if (wcscmp(candidates_t[i] -> Name(), class_name) == 0)
  374. class_sym = candidates_t[i];
  375. VariableSymbol *instance_sym = NULL;
  376. for (unsigned j = 0; !instance_sym && (j < class_sym -> declaration -> NumClassVariables()); j++)
  377. {
  378. AstFieldDeclaration* field_decl = class_sym -> declaration -> ClassVariable(j);
  379. for (unsigned vi = 0; vi < field_decl -> NumVariableDeclarators(); vi++)
  380. {
  381. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
  382. if (wcscmp(vd -> symbol -> Name(), instance_name) == 0)
  383. instance_sym = vd -> symbol;
  384. }
  385. }
  386. */
  387. //PrintSingletonXMI(class_sym , instance_sym, method_sym);
  388. Coutput << ((get_method_sym-> ACC_SYNCHRONIZED()) ? L"Multithreaded " : L"")
  389. << L"Singleton Pattern."
  390. << endl
  391. << candidates_t[i] -> Utf8Name() << " is a Singleton class"
  392. << endl
  393. << instance_sym -> Utf8Name() << " is the Singleton instance"
  394. << endl
  395. << get_method_sym -> Utf8Name() << " returns a " << instance_sym -> Utf8Name()
  396. << endl
  397. << "File location: " << candidates_t[i] -> file_symbol -> FileName()
  398. << endl
  399. << ((get_method_sym-> ACC_SYNCHRONIZED()) ? L"Double-checked Locking not used.\n" : L"\n")
  400. << endl;
  401. nSingleton++;
  402. }
  403. else
  404. {
  405. /*
  406. Coutput << L"Singleton Pattern"
  407. << endl
  408. << class_name << L" is a Singleton class"
  409. << endl
  410. << instance_name << L" is the Singleton instance"
  411. << endl
  412. << get_method << L" returns a " << instance_name
  413. << endl
  414. << L"File location: " << file_name
  415. << endl;
  416. Coutput << L"Warning: " << instance_name << L" is modified more than once." << endl << endl;
  417. */
  418. }
  419. delete env;
  420. }
  421. else
  422. {
  423. /*
  424. Coutput << L"Singleton Pattern"
  425. << endl
  426. << class_name << L" is a Singleton class"
  427. << endl
  428. << instance_name << L" is the Singleton instance"
  429. << endl
  430. << get_method << L" returns a " << instance_name
  431. << endl
  432. << L"File location: " << file_name
  433. << endl;
  434. Coutput << L"Warning: " << instance_name << L" is not returned in " << get_method << endl << endl;
  435. */
  436. }
  437. }
  438. }
  439. }
  440. }
  441. void FindChainOfResponsibility(ClassSymbolTable *cs_table, MethodSymbolTable* ms_table, DelegationTable *d_table, StoragePool *ast_pool)
  442. {
  443. if (PINOT_DEBUG)
  444. Coutput << "Identifying Cor and Decorator" << endl;
  445. SymbolSet CoR_cache;
  446. SymbolSet D_cache;
  447. vector<MethodSymbol*> cache;
  448. int i;
  449. for (i = 0; i< d_table -> size(); i++)
  450. {
  451. DelegationEntry *entry = d_table -> Entry(i);
  452. if (PINOT_DEBUG)
  453. Coutput << "Analyzing delegation: " << entry->enclosing->Utf8Name() << " -> " << entry->method->Utf8Name() << endl;
  454. if (entry-> vsym
  455. && (entry->from->IsSubtype(entry->vsym->Type()) || entry->vsym->Type()->IsSubtype(entry->from))
  456. && (!entry->vsym->IsLocal() || entry->from->Shadows(entry->vsym))
  457. && ((strcmp(entry -> method -> Utf8Name(), entry -> enclosing -> Utf8Name()) == 0) || (entry->method == entry->enclosing))
  458. && (strcmp(entry->enclosing->SignatureString(), entry->method->SignatureString()) == 0)
  459. )
  460. {
  461. unsigned j = 0;
  462. for (; (j < cache.size()) && (cache[j] != entry->enclosing) ; j++);
  463. if (j == cache.size())
  464. {
  465. ChainAnalysis chain_analysis(entry->vsym, entry->enclosing, ast_pool);
  466. ChainAnalysis::ResultTag result = chain_analysis.AnalyzeCallChain();
  467. if (result == ChainAnalysis::CoR)
  468. {
  469. Coutput << "Chain of Responsibility Pattern." << endl;
  470. Coutput << entry -> from -> Utf8Name() << " is a Chain of Responsibility Handler class" << endl;
  471. Coutput << entry -> enclosing -> Utf8Name() << " is a handle operation" << endl;
  472. Coutput << entry -> vsym -> Utf8Name() << " of type " << entry -> vsym -> Type() -> Utf8Name() << " propogates the request" << endl;
  473. char* file_name = entry -> enclosing -> containing_type -> file_symbol -> FileName();
  474. Coutput << L"File Location: " << file_name << endl << endl;
  475. cache.push_back(entry->enclosing);
  476. CoR_cache.AddElement(entry -> vsym -> Type());
  477. //nCoR++;
  478. }
  479. else if (result == ChainAnalysis::DECORATOR)
  480. {
  481. Coutput << "Decorator Pattern." << endl;
  482. Coutput << entry -> from -> Utf8Name() << " is a Decorator class" << endl;
  483. Coutput << entry -> enclosing -> Utf8Name() << " is a decorate operation" << endl;
  484. Coutput << entry -> vsym -> Utf8Name() << " of type " << entry -> vsym -> Type() -> Utf8Name() << " is the Decoratee class" << endl;
  485. char* file_name = entry -> enclosing -> containing_type -> file_symbol -> FileName();
  486. Coutput << L"File Location: " << file_name << endl << endl;
  487. cache.push_back(entry->enclosing);
  488. D_cache.AddElement(entry -> vsym -> Type());
  489. //nDecorator++;
  490. }
  491. chain_analysis.CleanUp();
  492. }
  493. }
  494. }
  495. nCoR += CoR_cache.Size();
  496. CoR_cache.Print();
  497. nDecorator += D_cache.Size();
  498. D_cache.Print();
  499. }
  500. void FindBridge(ClassSymbolTable *cs_table, DelegationTable *d_table)
  501. {
  502. multimap<TypeSymbol*,TypeSymbol*> cache;
  503. multimap<TypeSymbol*,TypeSymbol*> negatives;
  504. int i;
  505. for (i = 0; i < d_table -> size(); i++)
  506. {
  507. DelegationEntry *entry = d_table -> Entry(i);
  508. if (//(entry -> from -> ACC_ABSTRACT()) &&
  509. entry->from->subtypes
  510. && entry->from->subtypes->Size()
  511. && entry->to->ACC_INTERFACE()
  512. && entry->from->file_symbol->IsJava()
  513. && entry->to->file_symbol->IsJava()
  514. && (!cs_table -> Converge(entry -> from, entry -> to)))
  515. {
  516. multimap<TypeSymbol*,TypeSymbol*>::iterator p = cache.begin();
  517. for (; (p != cache.end()) && ((p -> first != entry -> from) || (p -> second != entry -> to)); p++);
  518. if ((p == cache.end()) && !d_table -> DelegatesSuccessors(entry -> from, entry -> to))
  519. {
  520. nBridge++;
  521. cache.insert(pair<TypeSymbol*,TypeSymbol*>(entry -> from, entry -> to));
  522. Coutput << "Bridge Pattern." << endl;
  523. Coutput << entry -> from -> Utf8Name()
  524. << " is abstract.\n"
  525. << entry -> to -> Utf8Name()
  526. << " is an interface.\n"
  527. << entry -> from -> Utf8Name()
  528. << " delegates "
  529. << entry -> to -> Utf8Name()
  530. << "."
  531. << endl
  532. << "File Location: "
  533. << entry -> from -> file_symbol -> FileName()
  534. << ",\n "
  535. << entry -> to -> file_symbol -> FileName()
  536. << endl;
  537. /*
  538. Coutput << "Subclasses of " << entry -> from -> Utf8Name() << ": ";
  539. cs_table -> PrintSubclasses(entry -> from);
  540. Coutput << "Subtypes of " << entry -> to -> Utf8Name() << ": ";
  541. cs_table -> PrintSubtypes(entry -> to);
  542. Coutput << "Subinterfaces of " << entry -> to -> Utf8Name() << ": ";
  543. cs_table -> PrintSubinterfaces(entry -> to);
  544. d_table -> Delegates(entry -> to, entry -> from);
  545. d_table -> ShowDelegations(entry -> from, entry -> to);
  546. */
  547. Coutput << endl;
  548. }
  549. }
  550. }
  551. }
  552. void FindFlyweight(MethodBodyTable* mb_table, GenTable* gen_table, AssocTable* assoc_table)
  553. {
  554. // Collecting possible flyweight pools
  555. vector<wchar_t*>* pools = NULL;
  556. int i;
  557. for (i = 0; i < assoc_table -> getSize(); i++)
  558. {
  559. if ((assoc_table -> getKindAt(i) == Assoc::IM)
  560. && (assoc_table -> getModeAt(i) == Assoc::PRIVATE)
  561. && (wcscmp(assoc_table -> getTypeAt(i), L"Hashtable") == 0))
  562. {
  563. wchar_t* class_name = assoc_table -> getClassNameAt(i);
  564. if (!pools)
  565. {
  566. pools = new vector<wchar_t*>();
  567. pools -> push_back(class_name);
  568. }
  569. else if (!isCached(class_name, pools))
  570. {
  571. pools -> push_back(class_name);
  572. }
  573. }
  574. }
  575. // Look for possible flyweight factories
  576. for (i = 0; i < assoc_table -> getSize(); i++)
  577. {
  578. if ((assoc_table -> getKindAt(i) == Assoc::MP)
  579. && (isCached(assoc_table ->getTypeAt(i), pools)))
  580. {
  581. wchar_t* package_name = assoc_table -> getPackageNameAt(i);
  582. wchar_t* flyweight_factory = assoc_table -> getClassNameAt(i);
  583. wchar_t* get_flyweight = assoc_table -> getMethodNameAt(i);
  584. AstMethodDeclaration *method_declaration = dynamic_cast<AstMethodDeclaration*>
  585. (mb_table -> getAstLocation(flyweight_factory, get_flyweight));
  586. AstMethodBody *method_body = method_declaration -> method_body_opt;
  587. // Given:
  588. // - type of flyweight class
  589. // - flyweight pool type and var_name
  590. wchar_t* flyweight = method_declaration -> getReturnType();
  591. wchar_t* pool = assoc_table ->getTypeAt(i);
  592. wchar_t* pool_name = assoc_table -> getNameAt(i);
  593. if (method_body
  594. && (!method_declaration -> isPrimitiveType(flyweight))
  595. && (wcscmp(pool, flyweight_factory) != 0))
  596. {
  597. //Coutput << "package name: " << package_name << endl
  598. // << "class name: " << flyweight_factory << endl
  599. // << "method name: " << get_flyweight << endl;
  600. // Check for variables of type "flyweight" declared in this method
  601. vector<wchar_t*>* vars = method_body -> getVariables(flyweight);
  602. if (vars && vars -> size() == 1)
  603. {
  604. wchar_t* temp = (*vars)[0];
  605. //Then make sure that this var is returned by the method
  606. if (method_body -> returnsVar(temp))
  607. {
  608. // If not, reject this class as a flyweight factory.
  609. // Look for a specific statechart on the var that gets returned from this method.
  610. // (1) SET --yes--> RETURN
  611. // (2) SET --no --> CREATE ----> SET ----> RETURN
  612. Statechart* statechart = method_body -> getStatechart(temp);
  613. //int i = 0;
  614. if ((statechart -> getStateKindAt(0) == State::SET)
  615. && (isCached( pool_name, statechart -> getStateParticipantsAt(0)))
  616. && (statechart -> getStateKindAt(1) == State::CONDITION)
  617. && (statechart -> getStateKindAt(2) == State::CREATE)
  618. && ((statechart -> getStateKindAt(3) == State::SET))
  619. && (isCached( pool_name, statechart -> getStateParticipantsAt(3)))
  620. && ((statechart -> getStateKindAt(4) == State::RETURN)))
  621. {
  622. Coutput << "Flyweight Pattern." << endl;
  623. Coutput << flyweight_factory
  624. << " is a Flyweight factory class. "
  625. << endl;
  626. Coutput << pool
  627. << " is a flyweight object pool."
  628. << endl;
  629. Coutput << get_flyweight
  630. << " returns a flyweight object."
  631. << endl;
  632. if (method_declaration -> isSynchronized())
  633. Coutput << "Consider using Double-checked Locking." << endl;
  634. Coutput << "File location: " << gen_table -> getFileName(flyweight_factory, package_name) << endl;
  635. Coutput << endl << endl;
  636. nFlyweight++;
  637. }
  638. }
  639. }
  640. }
  641. }
  642. }
  643. }
  644. void FindFlyweight1(MethodSymbolTable *ms_table)
  645. {
  646. if (PINOT_DEBUG)
  647. Coutput << "Identifying the Flyweight pattern" << endl;
  648. for (unsigned i=0; i<ms_table->size(); i++)
  649. {
  650. MethodSymbol *msym = (*ms_table)[i];
  651. if (PINOT_DEBUG)
  652. Coutput << "Analyzing method: " << msym->Utf8Name() << endl;
  653. TypeSymbol *unit_type = msym->containing_type;
  654. if ((msym->declaration->kind==Ast::METHOD)
  655. && msym->declaration->MethodDeclarationCast()->method_body_opt
  656. && msym->Type()->file_symbol
  657. && !unit_type->IsFamily(msym->Type())
  658. )
  659. {
  660. FlyweightAnalysis flyweight(msym);
  661. msym->declaration->MethodDeclarationCast()->method_body_opt->Accept(flyweight);
  662. //flyweight.DumpSummary();
  663. if (flyweight.IsFlyweightFactory())
  664. {
  665. nFlyweight++;
  666. nFlyweightGoFVersion++;
  667. Coutput << "Flyweight Pattern." << endl;
  668. Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
  669. Coutput << flyweight.GetFlyweightPool()->Utf8Name() << " is the flyweight pool." << endl;
  670. Coutput << msym->Utf8Name()
  671. << " is the factory method, producing flyweight objects of type "
  672. << msym->Type()->Utf8Name() << endl;
  673. Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
  674. }
  675. }
  676. }
  677. }
  678. void FindFlyweight2(ClassSymbolTable *cs_table, WriteAccessTable *w_table, ReadAccessTable *r_table)
  679. {
  680. // This strategy looks for a variant flyweight implementation, where
  681. // flyweight factories and pools are not necessary:
  682. //
  683. // 1. classes that are defined immutable
  684. // - class declared "final"
  685. // - allows instantiation, thus public ctors (unlike java.lang.Math)
  686. // - but internal fields should all be private and not written/modified by any non-private methods.
  687. //
  688. // 2. flyweight pools are represented as individual variable declarations
  689. // - such variables are typically declared "static final" and are initialized (pre-populated)
  690. unsigned c;
  691. for (c= 0; c < cs_table -> size(); c++)
  692. {
  693. TypeSymbol *unit_type = (*cs_table)[c];
  694. if (unit_type->ACC_FINAL())
  695. {
  696. AstClassBody *class_body = unit_type->declaration;
  697. if (!class_body -> default_constructor)
  698. {
  699. unsigned i, j;
  700. for (i=0; (i < class_body->NumConstructors()) && !class_body->Constructor(i)->constructor_symbol->ACC_PRIVATE(); i++)
  701. ;
  702. for (j=0; (j < unit_type->NumVariableSymbols()) && unit_type->VariableSym(j)->ACC_PRIVATE(); j++)
  703. ;
  704. if ((i == class_body->NumConstructors()) && (j == unit_type->NumVariableSymbols()))
  705. {
  706. bool flag = false;
  707. unsigned m, v;
  708. for (v = 0; !flag && (v < unit_type->NumVariableSymbols()); v++)
  709. {
  710. if (!unit_type->VariableSym(v)->ACC_FINAL())
  711. {
  712. for (m=0; !flag && (m < class_body->NumMethods()); m++)
  713. {
  714. if (class_body->Method(m)->method_symbol->ACC_PUBLIC())
  715. flag = w_table->IsWrittenBy(unit_type->VariableSym(v), class_body->Method(m)->method_symbol);
  716. }
  717. }
  718. }
  719. if (!flag)
  720. {
  721. nFlyweight++;
  722. Coutput << "Flyweight Pattern." << endl;
  723. Coutput << unit_type->Utf8Name() << " is immutable." << endl;
  724. Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
  725. nImmutable++;
  726. }
  727. }
  728. }
  729. }
  730. else
  731. {
  732. unsigned i;
  733. for (i=0; i < unit_type->NumVariableSymbols(); i++)
  734. {
  735. if (unit_type->VariableSym(i)->Type()->file_symbol
  736. && unit_type->VariableSym(i)->ACC_STATIC()
  737. && unit_type->VariableSym(i)->ACC_FINAL()
  738. //&& (unit_type != unit_type->VariableSym(i)->Type())
  739. )
  740. {
  741. if (unit_type->VariableSym(i)->ACC_PUBLIC() && unit_type->VariableSym(i)->declarator->variable_initializer_opt)
  742. {
  743. nFlyweight++;
  744. Coutput << "Flyweight Pattern." << endl;
  745. Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
  746. //Coutput << unit_type->VariableSym(i)->Utf8Name() << " is a flyweight object (declared public-static-final)." << endl;
  747. Coutput << unit_type->VariableSym(i)->Type()->Utf8Name() << " is a flyweight object (declared public-static-final)." << " object-name: "<< unit_type -> VariableSym(i) -> Utf8Name() << endl; //angor
  748. Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
  749. goto done;
  750. }
  751. else
  752. {
  753. VariableSymbol *vsym = unit_type->VariableSym(i);
  754. MethodSymbol *msym = NULL;
  755. multimap<VariableSymbol*,MethodSymbol*>::iterator p;
  756. for (p = r_table -> begin(); p != r_table -> end(); p++)
  757. {
  758. //Find the method that returns this static-final flyweight object.
  759. //NOTE: this approach does not analyze method body, just the fact that a flyweight object can be returned.
  760. //VariableSymbol *t1 = p->first;
  761. //MethodSymbol *t2 = p->second;
  762. if (strcmp(vsym->Type()->fully_qualified_name->value, "java/lang/String")
  763. && (p -> first == vsym))
  764. msym = p->second;
  765. else if (Utility::Aliasing(p->first, vsym))
  766. msym = p->second;
  767. }
  768. if (msym)
  769. {
  770. nFlyweight++;
  771. Coutput << "Flyweight Pattern." << endl;
  772. Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
  773. //Coutput << vsym->Utf8Name() << " is a flyweight object." << endl; //pinot
  774. Coutput << vsym->Type()->Utf8Name() << " is a flyweight object." <<" object-name: "<<vsym->Utf8Name()<< endl; //angor
  775. Coutput << msym->Utf8Name() << " is the getFlyweight method." << endl;
  776. Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
  777. goto done;
  778. }
  779. }
  780. }
  781. }
  782. done: ;
  783. }
  784. }
  785. }
  786. bool Connectivity(MethodSymbol* start, TypeSymbol *end, MethodSymbolTable *ms_table)
  787. {
  788. if (!start->invokers || !end->subtypes || (end->subtypes->Size()==0))
  789. return false;
  790. ms_table->ClearMarks();
  791. Symbol *sym = end->subtypes->FirstElement();
  792. while(sym)
  793. {
  794. TypeSymbol *type = sym->TypeCast();
  795. for (unsigned i = 0; i < type->NumMethodSymbols(); i++)
  796. {
  797. if (type->MethodSym(i)->declaration)
  798. {
  799. if ((type->MethodSym(i)->declaration->ConstructorDeclarationCast()
  800. && type->MethodSym(i)->declaration->ConstructorDeclarationCast()->constructor_body)
  801. || (type->MethodSym(i)->declaration->MethodDeclarationCast()
  802. && type->MethodSym(i)->declaration->MethodDeclarationCast()->method_body_opt))
  803. type->MethodSym(i)->mark = 'B';
  804. }
  805. }
  806. sym = end->subtypes->NextElement();
  807. }
  808. if (start->mark == 'B')
  809. {
  810. Coutput << start->Utf8Name() << " is called by " << start->containing_type->Utf8Name() << "::" << start->Utf8Name() << " is the pivot point." <<endl;
  811. return true;
  812. }
  813. SymbolSet set(0);
  814. sym = start->invokers->FirstElement();
  815. while(sym)
  816. {
  817. MethodSymbol *msym = sym->MethodCast();
  818. if (msym->mark == 'B')
  819. {
  820. Coutput << start->Utf8Name() << " is called by " << msym->containing_type->Utf8Name() << "::" << msym->Utf8Name() << " is the pivot point." <<endl;
  821. return true;
  822. }
  823. else
  824. {
  825. msym->mark = 'R';
  826. if (msym->invokers)
  827. set.Union(*msym->invokers);
  828. }
  829. sym = start->invokers->NextElement();
  830. }
  831. while(set.Size())
  832. {
  833. sym = set.FirstElement();
  834. while(sym)
  835. {
  836. MethodSymbol *msym = sym->MethodCast();
  837. if (msym->mark == 'B')
  838. {
  839. Coutput << msym->containing_type->Utf8Name() << "::" << msym->Utf8Name() << " is the pivot point." <<endl;
  840. return true;
  841. }
  842. else if (msym->mark == 'R')
  843. set.RemoveElement(msym);
  844. else if (msym->mark == 'W')
  845. {
  846. msym->mark = 'R';
  847. set.RemoveElement(msym);
  848. if (msym->invokers)
  849. set.Union(*msym->invokers);
  850. }
  851. sym = set.NextElement();
  852. }
  853. }
  854. return false;
  855. }
  856. bool DelegatesSuccessors(TypeSymbol *t1, TypeSymbol *t2)
  857. {
  858. // pre-condition: t1 is concrete, while t2 is abstract
  859. if (t2->subtypes)
  860. {
  861. Symbol *sym = t2->subtypes->FirstElement();
  862. while (sym)
  863. {
  864. // checks for delegations to concrete classes.
  865. // the reason is to make sure that concrete strategies are not drectly exposed to the context class.
  866. if (!sym->TypeCast()->ACC_ABSTRACT() && sym->TypeCast()->call_dependents && sym->TypeCast()->call_dependents->IsElement(t1))
  867. return true;
  868. sym = t2->subtypes->NextElement();
  869. }
  870. }
  871. return false;
  872. }
  873. void FindStrategy(ClassSymbolTable *cs_table, DelegationTable *d_table, WriteAccessTable *w_table, ReadAccessTable *r_table, MethodSymbolTable *ms_table)
  874. {
  875. multimap<TypeSymbol*,TypeSymbol*> cache;
  876. int i;
  877. for (i = 0; i < d_table -> size(); i++)
  878. {
  879. DelegationEntry *entry = d_table -> Entry(i);
  880. if ((!entry -> from -> ACC_ABSTRACT())
  881. && (!entry -> from -> Anonymous())
  882. && (entry -> to -> ACC_ABSTRACT())
  883. && (entry -> to -> file_symbol -> IsJava())
  884. && (entry -> base_opt)
  885. && !entry->from->IsFamily(entry->to)
  886. )
  887. {
  888. multimap<TypeSymbol*,TypeSymbol*>::iterator p = cache.begin();
  889. for (; (p != cache.end()) && ((p -> first != entry -> from) || (p -> second != entry -> to)) ; p++);
  890. if ((p == cache.end())
  891. && (!DelegatesSuccessors(entry -> from, entry -> to))
  892. )
  893. {
  894. VariableSymbol *vsym = NULL;
  895. //
  896. // Change THIS
  897. // entry->base_opt should be unwrapped to vsym/this/super/class.
  898. //
  899. if (entry -> base_opt -> kind == Ast::NAME)
  900. vsym = entry -> base_opt -> symbol -> VariableCast();
  901. else if (entry -> base_opt -> kind == Ast::CALL)
  902. {
  903. AstMethodInvocation *call = (entry -> base_opt -> MethodInvocationCast() -> resolution_opt)
  904. ? entry -> base_opt -> MethodInvocationCast() -> resolution_opt -> MethodInvocationCast()
  905. : entry -> base_opt -> MethodInvocationCast();
  906. MethodSymbol *msym = (MethodSymbol*) call -> symbol;
  907. multimap<VariableSymbol*,MethodSymbol*>::iterator p;
  908. //
  909. // Change THIS
  910. // a var can be returned by multiple methods.
  911. //
  912. for (p = r_table -> begin(); !vsym && (p != r_table -> end()); p++)
  913. {
  914. if (p -> second == msym)
  915. vsym = p -> first;
  916. }
  917. }
  918. if (vsym
  919. && ((! vsym-> IsLocal())
  920. ||(vsym = entry -> from -> Shadows(vsym))))
  921. {
  922. if ((entry -> from == vsym -> ContainingType())
  923. || ((entry -> from -> IsInner()) && (entry -> from -> ContainingType() == vsym -> ContainingType())))
  924. {
  925. cache.insert(pair<TypeSymbol*,TypeSymbol*>(entry->from, entry -> to));
  926. // check if State pattern is implemented.
  927. MethodSymbol *dsym = NULL;
  928. // if previous didn't work, try the following
  929. if (!dsym)
  930. {
  931. multimap<VariableSymbol*, MethodSymbol*>::iterator p;
  932. for (p = w_table->begin(); !dsym && p!=w_table->end();p++)
  933. {
  934. //VariableSymbol *t1 = p->first;
  935. //MethodSymbol *t2 = p->second;
  936. if (p->first==vsym)
  937. {
  938. if (Connectivity(p->second, entry->to, ms_table)
  939. )
  940. dsym = p->second;
  941. }
  942. }
  943. }
  944. if (dsym)
  945. {
  946. nState++;
  947. Coutput << "State Pattern." << endl;
  948. Coutput << entry -> from -> Utf8Name()
  949. << " is the Context class."
  950. << endl
  951. << entry -> to -> Utf8Name()
  952. << " is the State interface."
  953. << endl;
  954. Coutput << "Concrete State classes: ";
  955. entry->to->subtypes->Print();
  956. Coutput << "Delegation through "
  957. << vsym -> Utf8Name()
  958. << " of type "
  959. << vsym -> Type() -> Utf8Name()
  960. << endl
  961. << dsym -> Utf8Name()
  962. << " changes the state variable "
  963. << vsym -> Utf8Name()
  964. << endl;
  965. Coutput << dsym->Utf8Name()
  966. << " is invoked by ";
  967. dsym->callers->Print();
  968. Coutput << "File Location: "
  969. << entry -> from -> file_symbol -> FileName()
  970. << ",\n "
  971. << entry -> to -> file_symbol -> FileName()
  972. << endl
  973. << endl;
  974. }
  975. else
  976. {
  977. nStrategy++;
  978. Coutput << "Strategy Pattern." << endl;
  979. Coutput << entry -> from -> Utf8Name()
  980. << " is the Context class."
  981. << endl
  982. << entry -> to -> Utf8Name()
  983. << " is the Strategy interface."
  984. << endl;
  985. Coutput << "Concrete Strategy classes: ";
  986. entry->to->subtypes->Print();
  987. Coutput << "Delegation through "
  988. << vsym -> Utf8Name()
  989. << " of type "
  990. << vsym -> Type() -> Utf8Name()
  991. << endl
  992. << "File Location: "
  993. << entry -> from -> file_symbol -> FileName()
  994. << ",\n "
  995. << entry -> to -> file_symbol -> FileName()
  996. << endl
  997. << endl;
  998. }
  999. }
  1000. }
  1001. }
  1002. }
  1003. }
  1004. }
  1005. void FindStrategy1(ClassSymbolTable *cs_table, DelegationTable *d_table, WriteAccessTable *w_table, ReadAccessTable *r_table, MethodSymbolTable *ms_table)
  1006. {
  1007. multimap<TypeSymbol*,TypeSymbol*> cache;
  1008. unsigned c;
  1009. for (c = 0; c < cs_table->size(); c++)
  1010. {
  1011. TypeSymbol *context = (*cs_table)[c];
  1012. if (!context->ACC_ABSTRACT() && !context->Anonymous() && (!context->subtypes || !context->subtypes->Size()))
  1013. {
  1014. for (unsigned i = 0; i < context->NumVariableSymbols(); i++)
  1015. {
  1016. VariableSymbol *vsym = context->VariableSym(i);
  1017. if (vsym->Type()->file_symbol
  1018. && vsym->Type()->file_symbol->IsJava()
  1019. && vsym->Type()->ACC_ABSTRACT()
  1020. && !vsym->Type()->IsFamily(context)
  1021. && !vsym->Type()->IsArray()
  1022. //&& !vsym->Type()->IsSelfContaining()
  1023. )
  1024. {
  1025. MethodSymbol *dsym = NULL;
  1026. multimap<VariableSymbol*, MethodSymbol*>::iterator p;
  1027. bool flag = false;
  1028. for (p = w_table->begin(); !dsym && p!=w_table->end();p++)
  1029. {
  1030. //VariableSymbol *t1 = p->first;
  1031. //MethodSymbol *t2 = p->second;
  1032. if (p->first==vsym)
  1033. {
  1034. flag = true;
  1035. if (p->second->declaration
  1036. && p->second->declaration->MethodDeclarationCast()
  1037. && Connectivity(p->second, vsym->Type(), ms_table))
  1038. dsym = p->second;
  1039. }
  1040. }
  1041. if (dsym)
  1042. {
  1043. nState++;
  1044. Coutput << "State Pattern." << endl;
  1045. Coutput << context->Utf8Name() << " is the Context class." << endl
  1046. << vsym->Type()->Utf8Name() << " is the State interface." << endl;
  1047. Coutput << "Concrete State classes: ";
  1048. vsym->Type()->subtypes->Print();
  1049. Coutput << "Delegation through " << vsym->Utf8Name() << " of type " << vsym->Type()->Utf8Name() << endl
  1050. << dsym->Utf8Name() << " changes the state variable " << vsym->Utf8Name() << endl;
  1051. Coutput << dsym->Utf8Name() << " is invoked by ";
  1052. dsym->invokers->Print();
  1053. Coutput << "File Location: "
  1054. << context->file_symbol->FileName() << ",\n "
  1055. << vsym->Type()->file_symbol->FileName()
  1056. << endl
  1057. << endl;
  1058. }
  1059. else if (flag)
  1060. {
  1061. nStrategy++;
  1062. Coutput << "Strategy Pattern." << endl;
  1063. Coutput << context->Utf8Name() << " is the Context class." << endl
  1064. << vsym->Type()->Utf8Name() << " is the Strategy interface." << endl;
  1065. Coutput << "Concrete Strategy classes: ";
  1066. vsym->Type()->subtypes->Print();
  1067. Coutput << "Delegation through " << vsym->Utf8Name() << " of type " << vsym->Type()->Utf8Name() << endl;
  1068. Coutput << "File Location: "
  1069. << context->file_symbol->FileName() << ",\n "
  1070. << vsym->Type()->file_symbol->FileName()
  1071. << endl
  1072. << endl;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. }
  1078. }
  1079. void FindComposite(ClassSymbolTable *cs_table, DelegationTable *d_table)
  1080. {
  1081. unsigned c;
  1082. for (c = 0; c < cs_table -> size(); c++)
  1083. {
  1084. if (!(*cs_table)[c] -> ACC_ABSTRACT() && (*cs_table)[c]->supertypes_closure && (*cs_table)[c]->supertypes_closure->Size())
  1085. {
  1086. TypeSymbol *unit_type = (*cs_table)[c];
  1087. AstClassBody* class_body = unit_type -> declaration;
  1088. for (unsigned i = 0; i < class_body -> NumInstanceVariables(); i++)
  1089. {
  1090. AstFieldDeclaration* field_decl = class_body -> InstanceVariable(i);
  1091. for (unsigned vi = 0; (vi < field_decl -> NumVariableDeclarators()); vi++)
  1092. {
  1093. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
  1094. ContainerType *container_type = Utility::IdentifyContainerType(vd->symbol);
  1095. //TypeSymbol *contained_type = unit_type->IsOnetoMany(vd->symbol, d_table);
  1096. if (!container_type)
  1097. break;
  1098. if (container_type->kind == ContainerType::ARRAY)
  1099. {
  1100. if ((unit_type != vd->symbol->Type()->base_type)
  1101. && unit_type -> IsSubtype(vd->symbol->Type()->base_type))
  1102. {
  1103. nComposite++;
  1104. Coutput << "Composite Pattern." << endl;
  1105. Coutput << unit_type->Utf8Name() << " is the composite class." << endl;
  1106. Coutput << vd->symbol->Utf8Name() << " is the composite instance." << endl;
  1107. Coutput << vd->symbol->Type()->base_type->Utf8Name() << " is the component class." << endl;
  1108. Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl;
  1109. if (vd->symbol->Type()->base_type->file_symbol->IsClassOnly() && getenv("PINOT_HOME"))
  1110. Coutput << "$PINOT_HOME/lib/rt.jar" << vd->symbol->Type()->base_type->fully_qualified_name->value << ".class" << endl << endl;
  1111. else
  1112. Coutput << "File Location: " << vd->symbol->Type()->base_type->file_symbol->FileName() << endl << endl;
  1113. }
  1114. }
  1115. else
  1116. {
  1117. SymbolSet set;
  1118. set.Union(*unit_type->supertypes_closure);
  1119. int ct = 0;
  1120. for (int i = 0; i < d_table -> size(); i++)
  1121. {
  1122. DelegationEntry *entry = d_table -> Entry(i);
  1123. if (entry->vsym
  1124. && (entry->vsym == vd->symbol)
  1125. && container_type->IsPutMethod(entry->call->symbol->MethodCast()))
  1126. {
  1127. TypeSymbol *type = container_type->GetPutType(entry->call);
  1128. if (type && type->supertypes_closure)
  1129. {
  1130. type->supertypes_closure->AddElement(type);
  1131. set.Intersection(*type->supertypes_closure);
  1132. type->supertypes_closure->RemoveElement(type);
  1133. ct++;
  1134. }
  1135. }
  1136. }
  1137. if (ct == 0)
  1138. break;
  1139. //remove java/lang/Object from set
  1140. Utility::RemoveBuiltinInterfaces(set);
  1141. if (set.Size() == 0)
  1142. break;
  1143. nComposite++;
  1144. Coutput << "Composite pattern." << endl;
  1145. Coutput << unit_type->Utf8Name() << " is the composite class." << endl;
  1146. Coutput << vd->symbol->Utf8Name() << " is the composite instance." << endl;
  1147. Coutput << set.FirstElement()->TypeCast()->Utf8Name() << " is the component class." << endl;
  1148. Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl;
  1149. Coutput << "File Location: " << set.FirstElement()->TypeCast()->file_symbol->FileName() << endl << endl;
  1150. /*
  1151. if ((contained_type != unit_type) && contained_type && unit_type -> IsSubtype(contained_type))
  1152. {
  1153. nComposite++;
  1154. Coutput << "Composite pattern." << endl;
  1155. Coutput << unit_type -> Utf8Name() << " is the composite class." << endl;
  1156. Coutput << vd -> symbol -> Utf8Name() << " is the composite instance." << endl;
  1157. Coutput << contained_type -> Utf8Name() << " is the component class." << endl;
  1158. Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl;
  1159. Coutput << "File Location: " << contained_type -> file_symbol -> FileName() << endl << endl;
  1160. }
  1161. */
  1162. }
  1163. delete container_type;
  1164. }
  1165. }
  1166. }
  1167. }
  1168. }
  1169. void FindMediator(ClassSymbolTable *cs_table, DelegationTable *d_table)
  1170. {
  1171. unsigned c;
  1172. for (c = 0; c < cs_table -> size(); c++)
  1173. {
  1174. TypeSymbol *unit_type = (*cs_table)[c];
  1175. if (!unit_type -> ACC_INTERFACE()
  1176. && !unit_type -> IsInner()
  1177. && !unit_type -> ACC_PRIVATE())
  1178. {
  1179. SymbolSet colleagues;
  1180. SymbolSet observers;
  1181. SymbolSet *dset = unit_type -> references;
  1182. Symbol *sym = (dset) ? dset->FirstElement() : NULL;
  1183. while (sym)
  1184. {
  1185. TypeSymbol *type = sym -> TypeCast();
  1186. if (!type->Primitive()
  1187. && type -> ACC_ABSTRACT()
  1188. && !type -> ACC_INTERFACE()
  1189. && type -> references
  1190. && (unit_type != type)
  1191. && type -> file_symbol-> IsJava()
  1192. && type -> references -> IsElement(unit_type)
  1193. && unit_type -> IsOnetoMany(type))
  1194. {
  1195. if (d_table -> IsBidirectional(unit_type, type) == 3)
  1196. colleagues.AddElement(type);
  1197. else if (d_table -> IsBidirectional(unit_type, type) > 0)
  1198. observers.AddElement(type);
  1199. }
  1200. sym = dset->NextElement();
  1201. }
  1202. if (!colleagues.IsEmpty())
  1203. {
  1204. nMediator++;
  1205. Coutput << "Mediator pattern." << endl;
  1206. Coutput << unit_type -> Utf8Name() << " is a Mediator class." << endl;
  1207. Symbol *sym = NULL;
  1208. Coutput << "Colleagues: ";
  1209. sym = colleagues.FirstElement();
  1210. while (sym)
  1211. {
  1212. Coutput << sym -> TypeCast() -> Utf8Name() << " ";
  1213. sym = colleagues.NextElement();
  1214. }
  1215. Coutput << endl;
  1216. Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl << endl;
  1217. colleagues.SetEmpty();
  1218. }
  1219. else if (!observers.IsEmpty())
  1220. {
  1221. nObserver++;
  1222. Coutput << "Observer pattern." << endl;
  1223. Coutput << unit_type -> Utf8Name() << " is a Subject class." << endl;
  1224. Symbol *sym = NULL;
  1225. Coutput << "Observers: ";
  1226. sym = observers.FirstElement();
  1227. while (sym)
  1228. {
  1229. Coutput << sym -> TypeCast() -> Utf8Name() << " ";
  1230. sym = observers.NextElement();
  1231. }
  1232. Coutput << endl;
  1233. Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl << endl;
  1234. observers.SetEmpty();
  1235. }
  1236. }
  1237. }
  1238. }
  1239. bool IsJavaContainer(VariableSymbol *vsym)
  1240. {
  1241. if (strcmp(vsym->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
  1242. return true;
  1243. if (vsym->Type()->supertypes_closure)
  1244. {
  1245. Symbol *sym = vsym->Type()->supertypes_closure->FirstElement();
  1246. while (sym)
  1247. {
  1248. TypeSymbol *type = sym->TypeCast();
  1249. if (strcmp(type->fully_qualified_name->value, "java/util/Iterator") == 0)
  1250. return true;
  1251. sym = vsym->Type()->supertypes_closure->NextElement();
  1252. }
  1253. }
  1254. return false;
  1255. }
  1256. VariableSymbol *IteratorVar(AstExpression *expression)
  1257. {
  1258. /*
  1259. 1 - java.util.Iterator
  1260. 2 - array index
  1261. 3 - recursion
  1262. */
  1263. AstExpression *resolved = Utility::RemoveCasting(expression);
  1264. if (resolved->kind == Ast::CALL)
  1265. {
  1266. AstMethodInvocation *call = resolved->MethodInvocationCast();
  1267. if (call->base_opt
  1268. && call->base_opt->symbol->VariableCast()
  1269. && IsJavaContainer(call->base_opt->symbol->VariableCast())
  1270. && (strcmp(call->symbol->MethodCast()->Utf8Name(), "next") == 0))
  1271. return call -> base_opt -> NameCast() -> symbol -> VariableCast();
  1272. }
  1273. else if (resolved -> kind == Ast::ARRAY_ACCESS)
  1274. {
  1275. if (resolved -> ArrayAccessCast()->base-> kind == Ast::NAME)
  1276. return resolved -> ArrayAccessCast()->base->symbol->VariableCast();
  1277. }
  1278. else if ((resolved->kind == Ast::NAME) && (resolved->NameCast()->symbol->Kind()==Symbol::VARIABLE))
  1279. {
  1280. return resolved->NameCast()->symbol ->VariableCast();
  1281. }
  1282. return 0;
  1283. }
  1284. VariableSymbol *ListVar(VariableSymbol *vsym)
  1285. {
  1286. if (!vsym->declarator->variable_initializer_opt
  1287. || !vsym->declarator->variable_initializer_opt->ExpressionCast())
  1288. return NULL;
  1289. AstExpression *var_initializer = Utility::RemoveCasting(vsym->declarator->variable_initializer_opt->ExpressionCast());
  1290. // vsym -> IsLocal()
  1291. // vsym is an iterator that implements java.util.Iterator
  1292. if (strcmp( vsym->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
  1293. {
  1294. if (vsym -> declarator -> variable_initializer_opt -> kind == Ast::CALL)
  1295. {
  1296. AstMethodInvocation *init_call = vsym -> declarator -> variable_initializer_opt -> MethodInvocationCast();
  1297. // iterator initialized at declaration
  1298. if (strcmp(init_call -> symbol -> MethodCast() -> Utf8Name(), "iterator") == 0)
  1299. return (init_call->base_opt->symbol->Kind() == Symbol::VARIABLE)
  1300. ? init_call->base_opt->symbol->VariableCast()
  1301. : 0;
  1302. // iterator initialized later in an assignment statement
  1303. // vsym->owner is a Symbol, but if vsym is local then the owner is a MethodSymbol
  1304. // verify assignment statement
  1305. // if vsym is not local (which should be rare), and is initialized somewhere else (e.g. in other methods, also rare)
  1306. }
  1307. }
  1308. else if (strcmp( vsym->Type()->fully_qualified_name->value, "java/util/ListIterator") == 0)
  1309. {
  1310. if (vsym -> declarator -> variable_initializer_opt -> kind == Ast::CALL)
  1311. {
  1312. AstMethodInvocation *init_call = vsym -> declarator -> variable_initializer_opt -> MethodInvocationCast();
  1313. // iterator initialized at declaration
  1314. if (strcmp(init_call -> symbol -> MethodCast() -> Utf8Name(), "listIterator") == 0)
  1315. return init_call -> base_opt -> NameCast() -> symbol -> VariableCast();
  1316. // iterator initialized later in an assignment statement
  1317. // vsym->owner is a Symbol, but if vsym is local then the owner is a MethodSymbol
  1318. // verify assignment statement
  1319. // if vsym is not local (which should be rare), and is initialized somewhere else (e.g. in other methods, also rare)
  1320. }
  1321. }
  1322. else if ((vsym->declarator->variable_initializer_opt->kind == Ast::NAME)
  1323. && (vsym->declarator->variable_initializer_opt->NameCast()->symbol->Kind()==Symbol::VARIABLE))
  1324. {
  1325. return vsym->declarator->variable_initializer_opt->NameCast()->symbol->VariableCast();
  1326. }
  1327. else if (var_initializer->kind == Ast::CALL)
  1328. {
  1329. AstMethodInvocation *init_call = var_initializer->MethodInvocationCast();
  1330. if (init_call->base_opt && init_call->base_opt->symbol->VariableCast())
  1331. {
  1332. if (((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/Vector") == 0)
  1333. && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "elementAt") == 0))
  1334. || ((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/ArrayList") == 0)
  1335. && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "get") == 0))
  1336. )
  1337. return init_call->base_opt->symbol->VariableCast();
  1338. else if ((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
  1339. && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "next") == 0))
  1340. {
  1341. VariableSymbol *iterator = init_call->base_opt->symbol->VariableCast();
  1342. AstMethodInvocation *i_init_call = iterator->declarator->variable_initializer_opt->MethodInvocationCast();
  1343. // iterator initialized at declaration
  1344. if (strcmp(i_init_call->symbol->MethodCast()->Utf8Name(), "iterator") == 0)
  1345. return i_init_call->base_opt->symbol->VariableCast();
  1346. }
  1347. }
  1348. }
  1349. return NULL;
  1350. }
  1351. void FindObserver(ClassSymbolTable *cs_table, DelegationTable *d_table)
  1352. {
  1353. vector<TypeSymbol*> cache;
  1354. unsigned c;
  1355. for (c = 0; c < cs_table ->size(); c++)
  1356. {
  1357. TypeSymbol *unit_type = (*cs_table)[c];
  1358. if (!unit_type -> ACC_INTERFACE())
  1359. {
  1360. for (unsigned i = 0; i < unit_type -> declaration-> NumInstanceVariables(); i++)
  1361. {
  1362. AstFieldDeclaration* field_decl = unit_type -> declaration -> InstanceVariable(i);
  1363. for (unsigned vi = 0; vi < field_decl -> NumVariableDeclarators(); vi++)
  1364. {
  1365. AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
  1366. TypeSymbol *generic_type = unit_type -> IsOnetoMany(vd -> symbol, d_table) ;
  1367. if (generic_type && generic_type -> file_symbol)
  1368. {
  1369. for (int j = 0; j < d_table -> size(); j++)
  1370. {
  1371. DelegationEntry* entry = d_table -> Entry(j);
  1372. if ((unit_type == entry -> enclosing -> containing_type) && (generic_type == entry -> to))
  1373. {
  1374. /*
  1375. if ((unit_type == generic_type) && (entry -> vsym == vd -> symbol) && (entry -> enclosing == entry -> method) && (entry -> enclosing -> callers -> Size() > 1))
  1376. {
  1377. nObserver++;
  1378. Coutput << "Observer Pattern." << endl
  1379. << unit_type -> Utf8Name() << " is an observer iterator." << endl
  1380. << generic_type -> Utf8…

Large files files are truncated, but you can click here to view the full file