/lib/pinot/src/control.cpp
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
- // $Id: control.cpp,v 1.88 2006/03/15 06:19:48 shini Exp $
- //
- // This software is subject to the terms of the IBM Jikes Compiler
- // License Agreement available at the following URL:
- // http://ibm.com/developerworks/opensource/jikes.
- // Copyright (C) 1996, 2004 IBM Corporation and others. All Rights Reserved.
- // You must accept the terms of that agreement to use this software.
- //
- #include "control.h"
- #include "scanner.h"
- #include "parser.h"
- #include "semantic.h"
- #include "error.h"
- #include "bytecode.h"
- #include "case.h"
- #include "option.h"
- #include <fstream>
- #include <iomanip>
- #include <dlfcn.h>
- #include <stdlib.h>
- #ifdef HAVE_JIKES_NAMESPACE
- namespace Jikes { // Open namespace Jikes block
- #endif
- int counter1, counter2, counter3;
- int nSingleton, nCoR, nBridge, nStrategy, nState, nFlyweight, nComposite, nMediator, nTemplate, nFactoryMethod, nAbstractFactory, nVisitor, nDecorator, nObserver, nProxy, nAdapter, nFacade;
- bool PINOT_DEBUG;
- SymbolSet mediators;
- int nMediatorFacadeDual = 0, nFlyweightGoFVersion = 0, nImmutable = 0;
- /**
- * Utility functions
- */
- ContainerType *Utility::IdentifyContainerType(VariableSymbol *vsym)
- {
- TypeSymbol *type = vsym->Type();
- if (type->Primitive())
- return NULL;
- if (type->IsArray())
- // can be 2D, 3D, etc.
- return new ArrayContainer(vsym);
-
- if (strcmp(type->fully_qualified_name->value, "java/util/Vector") == 0)
- return new VectorContainer(vsym);
- else if (strcmp(type->fully_qualified_name->value, "java/util/ArrayList") == 0)
- return new ArrayListContainer(vsym);
- else if (strcmp(type->fully_qualified_name->value, "java/util/LinkedList") == 0)
- return new ArrayListContainer(vsym);
-
- if (type->supertypes_closure)
- {
- Symbol *sym= type->supertypes_closure->FirstElement();
- while(sym)
- {
- if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/util/Map") == 0)
- return new MapContainer(vsym);
- else if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/util/Collection") == 0)
- return new CollectionContainer(vsym);
- sym = type->supertypes_closure->NextElement();
- }
- }
- return NULL;
- }
- void Utility::RemoveJavaBaseClass(SymbolSet& set)
- {
- Symbol *sym = set.FirstElement();
- while(sym)
- {
- if (strcmp(sym->TypeCast()->fully_qualified_name->value, "java/lang/Object") == 0)
- {
- set.RemoveElement(sym);
- break;
- }
- sym = set.NextElement();
- }
- }
- void Utility::RemoveBuiltinInterfaces(SymbolSet& set)
- {
- SymbolSet temp;
- Symbol *sym = set.FirstElement();
- while(sym)
- {
- if (sym->TypeCast()->file_symbol->IsJava())
- temp.AddElement(sym);
- sym = set.NextElement();
- }
- set.Intersection(temp);
- }
- TypeSymbol *Utility::GetTypeSymbol(Symbol *sym)
- {
- if (sym->Kind() == Symbol::TYPE)
- return sym->TypeCast();
- else if (sym->Kind() == Symbol::VARIABLE)
- return sym->VariableCast()->Type();
- else if (sym->Kind() == Symbol::METHOD)
- return sym->MethodCast()->Type();
- else
- return NULL;
- }
- AstExpression *Utility::RemoveCasting(AstExpression *expr)
- {
- if (expr->kind == Ast::CAST)
- return RemoveCasting(expr->CastExpressionCast()->expression);
- else if (expr->kind == Ast::PARENTHESIZED_EXPRESSION)
- return RemoveCasting(expr->ParenthesizedExpressionCast()->expression);
- else
- return expr;
- }
- void Utility::Intersection(vector<signed>& a, vector<signed>& b, vector<signed>& c)
- {
- for (unsigned i = 0; i < a.size(); i++)
- for (unsigned j = 0; j < b.size(); j++)
- if (a[i] == b[j])
- c.push_back(a[i]);
- }
- void Utility::RemoveDuplicates(vector<signed>& a)
- {
- vector<signed> b;
- for (unsigned i = 0; i < a.size(); i++)
- {
- unsigned j = 0;
- while ((j < b.size()) && (a[i] != b[j])) j++;
- if (j == b.size())
- b.push_back(a[i]);
- }
- a.swap(b);
- }
- bool Utility::Aliasing(VariableSymbol *v1, VariableSymbol *v2)
- {
- if (!v1->aliases)
- return false;
- else if (v1->aliases->IsElement(v2))
- return true;
- else
- {
- Symbol *sym = v1->aliases->FirstElement();
- while(sym)
- {
- // reach two-hops only
- if (sym->VariableCast()->aliases && sym->VariableCast()->aliases->IsElement(v2))
- return true;
- sym = v1->aliases->NextElement();
- }
- return false;
- }
- }
- bool isCached(wchar_t* name, vector<wchar_t*>* cache)
- {
- bool flag = false;
- if (cache)
- {
- unsigned i = 0;
- while ((!flag) && (i < cache -> size()))
- {
- if (wcscmp((*cache)[i], name) == 0)
- flag = true;
- else
- i++;
- }
- }
- return flag;
- }
- bool intersection(vector<wchar_t*>* list1, vector<wchar_t*>* list2)
- {
- bool flag = false;
- if (list1 && list2)
- {
- unsigned i = 0, j;
- while (!flag && (i < list1 -> size()))
- {
- j = 0;
- while (!flag && (j < list2 -> size()))
- {
- if (wcscmp((*list1)[i], (*list2)[j]) == 0)
- flag = true;
- else
- j++;
- }
- if (!flag)
- i++;
- }
- }
- return flag;
- }
- void printVector(vector<wchar_t*>* v)
- {
- if (v)
- {
- unsigned i;
- for (i = 0; i < v -> size(); i++)
- {
- if (i > 0)
- Coutput << " ";
- Coutput << (*v)[i];
- }
- Coutput << endl;
- }
- }
- /**
- * GoF patterns
- */
- void PrintSingletonXMI(TypeSymbol *class_sym , VariableSymbol *instance_sym, MethodSymbol *method_sym);
- void FindPrototype(MethodBodyTable* mb_table, GenTable* gen_table, AssocTable* assoc_table)
- {
- vector<wchar_t*>* prototypes = NULL;
-
- prototypes = gen_table -> getSuccessors(L"Cloneable", GenTable::IMPL);
- if (prototypes)
- {
- unsigned i;
- for (i = 0; i < prototypes -> size(); i++)
- {
- int j;
- for (j = 0; j < assoc_table -> getSize(); j++)
- {
- if ((assoc_table -> getKindAt(j) == Assoc::MR)
- && (wcscmp(assoc_table -> getTypeAt(j), (*prototypes)[i]) == 0))
- {
- wchar_t* factory = assoc_table -> getClassNameAt(j);
- wchar_t* method_name = assoc_table -> getMethodNameAt(j);
- wchar_t* var_name = assoc_table -> getName(Assoc::CF, Assoc::PRIVATE, (*prototypes)[i], factory);
- AstMethodDeclaration* method_declaration = dynamic_cast<AstMethodDeclaration*>(mb_table -> getAstLocation(factory, method_name));
- AstMethodBody* method_body = method_declaration -> method_body_opt;
- Coutput << L"Prototype Factory: " << factory << endl
- << L"Make Method: " << method_name << endl
- << L"Prototype Var: " << var_name <<endl << endl;
- Coutput << L"AST of " << method_name << endl;
- method_body -> Print();
- if ((method_body -> NumStatements() == 1)
- && (method_body -> Statement(0) -> kind == Ast::RETURN))
- {
- AstReturnStatement* return_statement = dynamic_cast<AstReturnStatement*>(method_body -> Statement(0));
- if (return_statement -> expression_opt -> kind == Ast::CAST)
- {
- AstCastExpression* cast_expression = dynamic_cast<AstCastExpression*>(return_statement -> expression_opt);
- AstMethodInvocation* method_invocation = dynamic_cast<AstMethodInvocation*>(cast_expression -> expression);
- if ((wcscmp(method_invocation -> identifier_token_string, L"clone") == 0)
- && (wcscmp(dynamic_cast<AstName*>(method_invocation -> base_opt) -> identifier_token_string, var_name) == 0))
- Coutput << L"Yoohoo" << endl;
- }
- }
- Coutput << endl << endl;
- }
- }
- }
- }
- }
- void FindSingleton1(ClassSymbolTable *cs_table, StoragePool *ast_pool)
- {
- if (PINOT_DEBUG)
- Coutput << "Identifying the Singleton Pattern" << endl;
-
- for (unsigned c = 0; c < cs_table -> size(); c++)
- {
- TypeSymbol *unit_type = (*cs_table)[c];
- if (PINOT_DEBUG)
- Coutput << "Analyzing class: " << unit_type->fully_qualified_name->value << endl;
- //if (unit_type->Anonymous()) break;
-
- bool instantiable = true; //for Singleton pattern, either class is abtract or ctor is private
- VariableSymbol *instance = NULL;
- MethodSymbol *GetInstance = NULL;
-
- if (unit_type -> ACC_ABSTRACT())
- instantiable = false;
- for (unsigned i = 0; i < unit_type->NumVariableSymbols(); i++)
- {
- VariableSymbol *vsym = unit_type->VariableSym(i);
- if (vsym->ACC_PRIVATE() && vsym->ACC_STATIC() && (vsym->Type() == unit_type))
- {
- instance = vsym;
- break;
- }
- }
- for (unsigned i = 0; (instantiable || !GetInstance) && (i < unit_type->NumMethodSymbols()); i++)
- {
- MethodSymbol *msym = unit_type->MethodSym(i);
- if (msym->declaration)
- {
- if (msym->declaration->kind == Ast::CONSTRUCTOR)
- {
- if (msym->ACC_PRIVATE())
- instantiable = false;
- }
- else if (msym->declaration->kind == Ast::METHOD)
- {
- if (msym->ACC_PUBLIC() && msym->ACC_STATIC() && (msym->Type() == unit_type))
- GetInstance = msym;
- }
- }
- }
- if (!instantiable && instance && GetInstance)
- {
- // Do the behavioral analysis
- SingletonAnalysis singleton(instance, GetInstance, ast_pool);
- //Coutput << unit_type->file_symbol->FileName() << endl;
- if (singleton.ReturnsSingleton())
- {
- Coutput << ((GetInstance-> ACC_SYNCHRONIZED()) ? "" : "") << "Singleton Pattern." << endl
- << unit_type->Utf8Name() << " is a Singleton class" << endl
- << instance->Utf8Name() << " is the Singleton instance" << endl
- << GetInstance->Utf8Name() << " creates and returns " << instance->Utf8Name() << endl
- << "File location: " << unit_type->file_symbol->FileName() << endl
- << ((GetInstance->ACC_SYNCHRONIZED()) ? "Double-checked Locking not used.\n" : "\n") << endl;
- nSingleton++;
- }
- singleton.CleanUp();
- }
- }
- }
- void FindSingleton(ClassSymbolTable *cs_table, MethodSymbolTable* ms_table)
- {
- vector<TypeSymbol*> candidates_t;
-
- for (unsigned i = 0; i<ms_table->size(); i++)
- {
- MethodSymbol *method = (*ms_table)[i];
- if (method -> declaration -> kind == Ast::CONSTRUCTOR)
- {
- if (method -> ACC_PRIVATE())
- {
- TypeSymbol *unit_type = method -> containing_type;
- candidates_t.push_back(unit_type);
- }
- }
- }
- unsigned c;
- for (c = 0; c < cs_table -> size(); c++)
- {
- TypeSymbol *unit_type = (*cs_table)[c];
- if (unit_type -> ACC_ABSTRACT())
- {
- candidates_t.push_back(unit_type);
- }
- }
- if (candidates_t.size() > 0)
- {
- unsigned i;
- for (i = 0; i < candidates_t.size(); i++)
- {
- AstClassBody *class_body = candidates_t[i] -> declaration;
- // find the class variable
- VariableSymbol *instance_sym = NULL;
- for (unsigned j = 0; !instance_sym && (j < class_body -> NumClassVariables()); j++)
- {
- AstFieldDeclaration* field_decl = class_body -> ClassVariable(j);
- TypeSymbol *type = field_decl -> type -> symbol;
- if ((type == candidates_t[i]) && (field_decl -> NumVariableDeclarators() == 1))
- {
- AstVariableDeclarator* vd = field_decl -> VariableDeclarator(0);
- if (vd -> symbol -> ACC_PRIVATE())
- instance_sym = vd -> symbol;
- }
- }
- // find the get_instance method
- MethodSymbol *get_method_sym = NULL;
- for (unsigned j = 0; !get_method_sym && (j < class_body -> NumMethods()); j++)
- {
- AstMethodDeclaration* method = class_body -> Method(j);
- if ((method -> method_symbol)
- && (method -> method_symbol -> Type() == candidates_t[i])
- && (method -> method_symbol -> ACC_STATIC())
- && (method -> method_symbol -> ACC_PUBLIC()))
- get_method_sym = method -> method_symbol;
- }
-
- if (instance_sym && get_method_sym)
- {
- AstMethodDeclaration *method_declaration = get_method_sym -> declaration -> MethodDeclarationCast();
- AstMethodBody *method_body = method_declaration -> method_body_opt;
- wchar_t *instance_name = const_cast<wchar_t*>(instance_sym -> Name());
- if (method_body -> returnsVar(instance_name))
- {
- EnvTable *env = new EnvTable();
- env -> addEnvironment(instance_name, Env::INIT);
- method_body -> simulate(env);
- if (env -> getState(instance_name) == Env::INIT)
- {
- /*
- char* file_name = method_sym -> containing_type -> file_symbol -> FileName();
- TypeSymbol *class_sym = NULL;
- for (unsigned i = 0; !class_sym && (i < candidates_t.size()); i++)
- if (wcscmp(candidates_t[i] -> Name(), class_name) == 0)
- class_sym = candidates_t[i];
- VariableSymbol *instance_sym = NULL;
- for (unsigned j = 0; !instance_sym && (j < class_sym -> declaration -> NumClassVariables()); j++)
- {
- AstFieldDeclaration* field_decl = class_sym -> declaration -> ClassVariable(j);
- for (unsigned vi = 0; vi < field_decl -> NumVariableDeclarators(); vi++)
- {
- AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
- if (wcscmp(vd -> symbol -> Name(), instance_name) == 0)
- instance_sym = vd -> symbol;
- }
- }
- */
- //PrintSingletonXMI(class_sym , instance_sym, method_sym);
- Coutput << ((get_method_sym-> ACC_SYNCHRONIZED()) ? L"Multithreaded " : L"")
- << L"Singleton Pattern."
- << endl
- << candidates_t[i] -> Utf8Name() << " is a Singleton class"
- << endl
- << instance_sym -> Utf8Name() << " is the Singleton instance"
- << endl
- << get_method_sym -> Utf8Name() << " returns a " << instance_sym -> Utf8Name()
- << endl
- << "File location: " << candidates_t[i] -> file_symbol -> FileName()
- << endl
- << ((get_method_sym-> ACC_SYNCHRONIZED()) ? L"Double-checked Locking not used.\n" : L"\n")
- << endl;
- nSingleton++;
- }
- else
- {
- /*
- Coutput << L"Singleton Pattern"
- << endl
- << class_name << L" is a Singleton class"
- << endl
- << instance_name << L" is the Singleton instance"
- << endl
- << get_method << L" returns a " << instance_name
- << endl
- << L"File location: " << file_name
- << endl;
- Coutput << L"Warning: " << instance_name << L" is modified more than once." << endl << endl;
- */
- }
- delete env;
- }
- else
- {
- /*
- Coutput << L"Singleton Pattern"
- << endl
- << class_name << L" is a Singleton class"
- << endl
- << instance_name << L" is the Singleton instance"
- << endl
- << get_method << L" returns a " << instance_name
- << endl
- << L"File location: " << file_name
- << endl;
- Coutput << L"Warning: " << instance_name << L" is not returned in " << get_method << endl << endl;
- */
- }
- }
- }
- }
- }
- void FindChainOfResponsibility(ClassSymbolTable *cs_table, MethodSymbolTable* ms_table, DelegationTable *d_table, StoragePool *ast_pool)
- {
- if (PINOT_DEBUG)
- Coutput << "Identifying Cor and Decorator" << endl;
- SymbolSet CoR_cache;
- SymbolSet D_cache;
-
- vector<MethodSymbol*> cache;
- int i;
- for (i = 0; i< d_table -> size(); i++)
- {
- DelegationEntry *entry = d_table -> Entry(i);
- if (PINOT_DEBUG)
- Coutput << "Analyzing delegation: " << entry->enclosing->Utf8Name() << " -> " << entry->method->Utf8Name() << endl;
- if (entry-> vsym
- && (entry->from->IsSubtype(entry->vsym->Type()) || entry->vsym->Type()->IsSubtype(entry->from))
- && (!entry->vsym->IsLocal() || entry->from->Shadows(entry->vsym))
- && ((strcmp(entry -> method -> Utf8Name(), entry -> enclosing -> Utf8Name()) == 0) || (entry->method == entry->enclosing))
- && (strcmp(entry->enclosing->SignatureString(), entry->method->SignatureString()) == 0)
- )
- {
- unsigned j = 0;
- for (; (j < cache.size()) && (cache[j] != entry->enclosing) ; j++);
- if (j == cache.size())
- {
- ChainAnalysis chain_analysis(entry->vsym, entry->enclosing, ast_pool);
- ChainAnalysis::ResultTag result = chain_analysis.AnalyzeCallChain();
- if (result == ChainAnalysis::CoR)
- {
- Coutput << "Chain of Responsibility Pattern." << endl;
- Coutput << entry -> from -> Utf8Name() << " is a Chain of Responsibility Handler class" << endl;
- Coutput << entry -> enclosing -> Utf8Name() << " is a handle operation" << endl;
- Coutput << entry -> vsym -> Utf8Name() << " of type " << entry -> vsym -> Type() -> Utf8Name() << " propogates the request" << endl;
- char* file_name = entry -> enclosing -> containing_type -> file_symbol -> FileName();
- Coutput << L"File Location: " << file_name << endl << endl;
- cache.push_back(entry->enclosing);
- CoR_cache.AddElement(entry -> vsym -> Type());
- //nCoR++;
- }
- else if (result == ChainAnalysis::DECORATOR)
- {
- Coutput << "Decorator Pattern." << endl;
- Coutput << entry -> from -> Utf8Name() << " is a Decorator class" << endl;
- Coutput << entry -> enclosing -> Utf8Name() << " is a decorate operation" << endl;
- Coutput << entry -> vsym -> Utf8Name() << " of type " << entry -> vsym -> Type() -> Utf8Name() << " is the Decoratee class" << endl;
- char* file_name = entry -> enclosing -> containing_type -> file_symbol -> FileName();
- Coutput << L"File Location: " << file_name << endl << endl;
- cache.push_back(entry->enclosing);
- D_cache.AddElement(entry -> vsym -> Type());
- //nDecorator++;
- }
- chain_analysis.CleanUp();
- }
- }
- }
- nCoR += CoR_cache.Size();
- CoR_cache.Print();
- nDecorator += D_cache.Size();
- D_cache.Print();
- }
- void FindBridge(ClassSymbolTable *cs_table, DelegationTable *d_table)
- {
- multimap<TypeSymbol*,TypeSymbol*> cache;
- multimap<TypeSymbol*,TypeSymbol*> negatives;
-
- int i;
- for (i = 0; i < d_table -> size(); i++)
- {
- DelegationEntry *entry = d_table -> Entry(i);
- if (//(entry -> from -> ACC_ABSTRACT()) &&
- entry->from->subtypes
- && entry->from->subtypes->Size()
- && entry->to->ACC_INTERFACE()
- && entry->from->file_symbol->IsJava()
- && entry->to->file_symbol->IsJava()
- && (!cs_table -> Converge(entry -> from, entry -> to)))
- {
- multimap<TypeSymbol*,TypeSymbol*>::iterator p = cache.begin();
- for (; (p != cache.end()) && ((p -> first != entry -> from) || (p -> second != entry -> to)); p++);
- if ((p == cache.end()) && !d_table -> DelegatesSuccessors(entry -> from, entry -> to))
- {
- nBridge++;
- cache.insert(pair<TypeSymbol*,TypeSymbol*>(entry -> from, entry -> to));
- Coutput << "Bridge Pattern." << endl;
- Coutput << entry -> from -> Utf8Name()
- << " is abstract.\n"
- << entry -> to -> Utf8Name()
- << " is an interface.\n"
- << entry -> from -> Utf8Name()
- << " delegates "
- << entry -> to -> Utf8Name()
- << "."
- << endl
- << "File Location: "
- << entry -> from -> file_symbol -> FileName()
- << ",\n "
- << entry -> to -> file_symbol -> FileName()
- << endl;
- /*
- Coutput << "Subclasses of " << entry -> from -> Utf8Name() << ": ";
- cs_table -> PrintSubclasses(entry -> from);
-
- Coutput << "Subtypes of " << entry -> to -> Utf8Name() << ": ";
- cs_table -> PrintSubtypes(entry -> to);
-
- Coutput << "Subinterfaces of " << entry -> to -> Utf8Name() << ": ";
- cs_table -> PrintSubinterfaces(entry -> to);
- d_table -> Delegates(entry -> to, entry -> from);
- d_table -> ShowDelegations(entry -> from, entry -> to);
- */
- Coutput << endl;
-
- }
- }
- }
- }
- void FindFlyweight(MethodBodyTable* mb_table, GenTable* gen_table, AssocTable* assoc_table)
- {
- // Collecting possible flyweight pools
- vector<wchar_t*>* pools = NULL;
- int i;
- for (i = 0; i < assoc_table -> getSize(); i++)
- {
- if ((assoc_table -> getKindAt(i) == Assoc::IM)
- && (assoc_table -> getModeAt(i) == Assoc::PRIVATE)
- && (wcscmp(assoc_table -> getTypeAt(i), L"Hashtable") == 0))
- {
- wchar_t* class_name = assoc_table -> getClassNameAt(i);
- if (!pools)
- {
- pools = new vector<wchar_t*>();
- pools -> push_back(class_name);
- }
- else if (!isCached(class_name, pools))
- {
- pools -> push_back(class_name);
- }
- }
- }
- // Look for possible flyweight factories
- for (i = 0; i < assoc_table -> getSize(); i++)
- {
- if ((assoc_table -> getKindAt(i) == Assoc::MP)
- && (isCached(assoc_table ->getTypeAt(i), pools)))
- {
- wchar_t* package_name = assoc_table -> getPackageNameAt(i);
- wchar_t* flyweight_factory = assoc_table -> getClassNameAt(i);
- wchar_t* get_flyweight = assoc_table -> getMethodNameAt(i);
-
- AstMethodDeclaration *method_declaration = dynamic_cast<AstMethodDeclaration*>
- (mb_table -> getAstLocation(flyweight_factory, get_flyweight));
- AstMethodBody *method_body = method_declaration -> method_body_opt;
- // Given:
- // - type of flyweight class
- // - flyweight pool type and var_name
- wchar_t* flyweight = method_declaration -> getReturnType();
- wchar_t* pool = assoc_table ->getTypeAt(i);
- wchar_t* pool_name = assoc_table -> getNameAt(i);
- if (method_body
- && (!method_declaration -> isPrimitiveType(flyweight))
- && (wcscmp(pool, flyweight_factory) != 0))
- {
- //Coutput << "package name: " << package_name << endl
- // << "class name: " << flyweight_factory << endl
- // << "method name: " << get_flyweight << endl;
-
- // Check for variables of type "flyweight" declared in this method
- vector<wchar_t*>* vars = method_body -> getVariables(flyweight);
- if (vars && vars -> size() == 1)
- {
- wchar_t* temp = (*vars)[0];
- //Then make sure that this var is returned by the method
- if (method_body -> returnsVar(temp))
- {
- // If not, reject this class as a flyweight factory.
-
- // Look for a specific statechart on the var that gets returned from this method.
- // (1) SET --yes--> RETURN
- // (2) SET --no --> CREATE ----> SET ----> RETURN
- Statechart* statechart = method_body -> getStatechart(temp);
- //int i = 0;
- if ((statechart -> getStateKindAt(0) == State::SET)
- && (isCached( pool_name, statechart -> getStateParticipantsAt(0)))
- && (statechart -> getStateKindAt(1) == State::CONDITION)
- && (statechart -> getStateKindAt(2) == State::CREATE)
- && ((statechart -> getStateKindAt(3) == State::SET))
- && (isCached( pool_name, statechart -> getStateParticipantsAt(3)))
- && ((statechart -> getStateKindAt(4) == State::RETURN)))
- {
- Coutput << "Flyweight Pattern." << endl;
- Coutput << flyweight_factory
- << " is a Flyweight factory class. "
- << endl;
- Coutput << pool
- << " is a flyweight object pool."
- << endl;
-
- Coutput << get_flyweight
- << " returns a flyweight object."
- << endl;
- if (method_declaration -> isSynchronized())
- Coutput << "Consider using Double-checked Locking." << endl;
- Coutput << "File location: " << gen_table -> getFileName(flyweight_factory, package_name) << endl;
- Coutput << endl << endl;
- nFlyweight++;
- }
- }
- }
- }
- }
- }
- }
- void FindFlyweight1(MethodSymbolTable *ms_table)
- {
- if (PINOT_DEBUG)
- Coutput << "Identifying the Flyweight pattern" << endl;
-
- for (unsigned i=0; i<ms_table->size(); i++)
- {
- MethodSymbol *msym = (*ms_table)[i];
- if (PINOT_DEBUG)
- Coutput << "Analyzing method: " << msym->Utf8Name() << endl;
- TypeSymbol *unit_type = msym->containing_type;
- if ((msym->declaration->kind==Ast::METHOD)
- && msym->declaration->MethodDeclarationCast()->method_body_opt
- && msym->Type()->file_symbol
- && !unit_type->IsFamily(msym->Type())
- )
- {
- FlyweightAnalysis flyweight(msym);
- msym->declaration->MethodDeclarationCast()->method_body_opt->Accept(flyweight);
- //flyweight.DumpSummary();
- if (flyweight.IsFlyweightFactory())
- {
- nFlyweight++;
- nFlyweightGoFVersion++;
- Coutput << "Flyweight Pattern." << endl;
- Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
- Coutput << flyweight.GetFlyweightPool()->Utf8Name() << " is the flyweight pool." << endl;
- Coutput << msym->Utf8Name()
- << " is the factory method, producing flyweight objects of type "
- << msym->Type()->Utf8Name() << endl;
- Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
- }
- }
- }
- }
- void FindFlyweight2(ClassSymbolTable *cs_table, WriteAccessTable *w_table, ReadAccessTable *r_table)
- {
- // This strategy looks for a variant flyweight implementation, where
- // flyweight factories and pools are not necessary:
- //
- // 1. classes that are defined immutable
- // - class declared "final"
- // - allows instantiation, thus public ctors (unlike java.lang.Math)
- // - but internal fields should all be private and not written/modified by any non-private methods.
- //
- // 2. flyweight pools are represented as individual variable declarations
- // - such variables are typically declared "static final" and are initialized (pre-populated)
- unsigned c;
- for (c= 0; c < cs_table -> size(); c++)
- {
- TypeSymbol *unit_type = (*cs_table)[c];
- if (unit_type->ACC_FINAL())
- {
- AstClassBody *class_body = unit_type->declaration;
- if (!class_body -> default_constructor)
- {
- unsigned i, j;
- for (i=0; (i < class_body->NumConstructors()) && !class_body->Constructor(i)->constructor_symbol->ACC_PRIVATE(); i++)
- ;
- for (j=0; (j < unit_type->NumVariableSymbols()) && unit_type->VariableSym(j)->ACC_PRIVATE(); j++)
- ;
- if ((i == class_body->NumConstructors()) && (j == unit_type->NumVariableSymbols()))
- {
- bool flag = false;
- unsigned m, v;
- for (v = 0; !flag && (v < unit_type->NumVariableSymbols()); v++)
- {
- if (!unit_type->VariableSym(v)->ACC_FINAL())
- {
- for (m=0; !flag && (m < class_body->NumMethods()); m++)
- {
- if (class_body->Method(m)->method_symbol->ACC_PUBLIC())
- flag = w_table->IsWrittenBy(unit_type->VariableSym(v), class_body->Method(m)->method_symbol);
- }
- }
- }
- if (!flag)
- {
- nFlyweight++;
- Coutput << "Flyweight Pattern." << endl;
- Coutput << unit_type->Utf8Name() << " is immutable." << endl;
- Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
- nImmutable++;
- }
- }
- }
- }
- else
- {
- unsigned i;
- for (i=0; i < unit_type->NumVariableSymbols(); i++)
- {
- if (unit_type->VariableSym(i)->Type()->file_symbol
- && unit_type->VariableSym(i)->ACC_STATIC()
- && unit_type->VariableSym(i)->ACC_FINAL()
- //&& (unit_type != unit_type->VariableSym(i)->Type())
- )
- {
- if (unit_type->VariableSym(i)->ACC_PUBLIC() && unit_type->VariableSym(i)->declarator->variable_initializer_opt)
- {
- nFlyweight++;
- Coutput << "Flyweight Pattern." << endl;
- Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
- //Coutput << unit_type->VariableSym(i)->Utf8Name() << " is a flyweight object (declared public-static-final)." << endl;
- Coutput << unit_type->VariableSym(i)->Type()->Utf8Name() << " is a flyweight object (declared public-static-final)." << " object-name: "<< unit_type -> VariableSym(i) -> Utf8Name() << endl; //angor
- Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
- goto done;
- }
- else
- {
- VariableSymbol *vsym = unit_type->VariableSym(i);
- MethodSymbol *msym = NULL;
- multimap<VariableSymbol*,MethodSymbol*>::iterator p;
- for (p = r_table -> begin(); p != r_table -> end(); p++)
- {
- //Find the method that returns this static-final flyweight object.
- //NOTE: this approach does not analyze method body, just the fact that a flyweight object can be returned.
- //VariableSymbol *t1 = p->first;
- //MethodSymbol *t2 = p->second;
- if (strcmp(vsym->Type()->fully_qualified_name->value, "java/lang/String")
- && (p -> first == vsym))
- msym = p->second;
- else if (Utility::Aliasing(p->first, vsym))
- msym = p->second;
- }
-
- if (msym)
- {
- nFlyweight++;
- Coutput << "Flyweight Pattern." << endl;
- Coutput << unit_type->Utf8Name() << " is a flyweight factory." << endl;
- //Coutput << vsym->Utf8Name() << " is a flyweight object." << endl; //pinot
- Coutput << vsym->Type()->Utf8Name() << " is a flyweight object." <<" object-name: "<<vsym->Utf8Name()<< endl; //angor
- Coutput << msym->Utf8Name() << " is the getFlyweight method." << endl;
- Coutput << "File location: " << unit_type->file_symbol->FileName() << endl << endl;
- goto done;
- }
- }
- }
- }
- done: ;
- }
- }
- }
- bool Connectivity(MethodSymbol* start, TypeSymbol *end, MethodSymbolTable *ms_table)
- {
- if (!start->invokers || !end->subtypes || (end->subtypes->Size()==0))
- return false;
- ms_table->ClearMarks();
- Symbol *sym = end->subtypes->FirstElement();
- while(sym)
- {
- TypeSymbol *type = sym->TypeCast();
- for (unsigned i = 0; i < type->NumMethodSymbols(); i++)
- {
- if (type->MethodSym(i)->declaration)
- {
- if ((type->MethodSym(i)->declaration->ConstructorDeclarationCast()
- && type->MethodSym(i)->declaration->ConstructorDeclarationCast()->constructor_body)
- || (type->MethodSym(i)->declaration->MethodDeclarationCast()
- && type->MethodSym(i)->declaration->MethodDeclarationCast()->method_body_opt))
- type->MethodSym(i)->mark = 'B';
- }
- }
- sym = end->subtypes->NextElement();
- }
- if (start->mark == 'B')
- {
- Coutput << start->Utf8Name() << " is called by " << start->containing_type->Utf8Name() << "::" << start->Utf8Name() << " is the pivot point." <<endl;
- return true;
- }
- SymbolSet set(0);
- sym = start->invokers->FirstElement();
- while(sym)
- {
- MethodSymbol *msym = sym->MethodCast();
- if (msym->mark == 'B')
- {
- Coutput << start->Utf8Name() << " is called by " << msym->containing_type->Utf8Name() << "::" << msym->Utf8Name() << " is the pivot point." <<endl;
- return true;
- }
- else
- {
- msym->mark = 'R';
- if (msym->invokers)
- set.Union(*msym->invokers);
- }
- sym = start->invokers->NextElement();
- }
- while(set.Size())
- {
- sym = set.FirstElement();
- while(sym)
- {
- MethodSymbol *msym = sym->MethodCast();
- if (msym->mark == 'B')
- {
- Coutput << msym->containing_type->Utf8Name() << "::" << msym->Utf8Name() << " is the pivot point." <<endl;
- return true;
- }
- else if (msym->mark == 'R')
- set.RemoveElement(msym);
- else if (msym->mark == 'W')
- {
- msym->mark = 'R';
- set.RemoveElement(msym);
- if (msym->invokers)
- set.Union(*msym->invokers);
- }
- sym = set.NextElement();
- }
- }
- return false;
- }
- bool DelegatesSuccessors(TypeSymbol *t1, TypeSymbol *t2)
- {
- // pre-condition: t1 is concrete, while t2 is abstract
- if (t2->subtypes)
- {
- Symbol *sym = t2->subtypes->FirstElement();
- while (sym)
- {
- // checks for delegations to concrete classes.
- // the reason is to make sure that concrete strategies are not drectly exposed to the context class.
- if (!sym->TypeCast()->ACC_ABSTRACT() && sym->TypeCast()->call_dependents && sym->TypeCast()->call_dependents->IsElement(t1))
- return true;
- sym = t2->subtypes->NextElement();
- }
- }
- return false;
- }
- void FindStrategy(ClassSymbolTable *cs_table, DelegationTable *d_table, WriteAccessTable *w_table, ReadAccessTable *r_table, MethodSymbolTable *ms_table)
- {
- multimap<TypeSymbol*,TypeSymbol*> cache;
-
- int i;
- for (i = 0; i < d_table -> size(); i++)
- {
- DelegationEntry *entry = d_table -> Entry(i);
- if ((!entry -> from -> ACC_ABSTRACT())
- && (!entry -> from -> Anonymous())
- && (entry -> to -> ACC_ABSTRACT())
- && (entry -> to -> file_symbol -> IsJava())
- && (entry -> base_opt)
- && !entry->from->IsFamily(entry->to)
- )
- {
- multimap<TypeSymbol*,TypeSymbol*>::iterator p = cache.begin();
- for (; (p != cache.end()) && ((p -> first != entry -> from) || (p -> second != entry -> to)) ; p++);
- if ((p == cache.end())
- && (!DelegatesSuccessors(entry -> from, entry -> to))
- )
- {
- VariableSymbol *vsym = NULL;
- //
- // Change THIS
- // entry->base_opt should be unwrapped to vsym/this/super/class.
- //
- if (entry -> base_opt -> kind == Ast::NAME)
- vsym = entry -> base_opt -> symbol -> VariableCast();
- else if (entry -> base_opt -> kind == Ast::CALL)
- {
- AstMethodInvocation *call = (entry -> base_opt -> MethodInvocationCast() -> resolution_opt)
- ? entry -> base_opt -> MethodInvocationCast() -> resolution_opt -> MethodInvocationCast()
- : entry -> base_opt -> MethodInvocationCast();
- MethodSymbol *msym = (MethodSymbol*) call -> symbol;
- multimap<VariableSymbol*,MethodSymbol*>::iterator p;
- //
- // Change THIS
- // a var can be returned by multiple methods.
- //
- for (p = r_table -> begin(); !vsym && (p != r_table -> end()); p++)
- {
- if (p -> second == msym)
- vsym = p -> first;
- }
- }
- if (vsym
- && ((! vsym-> IsLocal())
- ||(vsym = entry -> from -> Shadows(vsym))))
- {
- if ((entry -> from == vsym -> ContainingType())
- || ((entry -> from -> IsInner()) && (entry -> from -> ContainingType() == vsym -> ContainingType())))
- {
- cache.insert(pair<TypeSymbol*,TypeSymbol*>(entry->from, entry -> to));
- // check if State pattern is implemented.
- MethodSymbol *dsym = NULL;
- // if previous didn't work, try the following
- if (!dsym)
- {
- multimap<VariableSymbol*, MethodSymbol*>::iterator p;
- for (p = w_table->begin(); !dsym && p!=w_table->end();p++)
- {
- //VariableSymbol *t1 = p->first;
- //MethodSymbol *t2 = p->second;
- if (p->first==vsym)
- {
- if (Connectivity(p->second, entry->to, ms_table)
- )
- dsym = p->second;
- }
- }
- }
- if (dsym)
- {
- nState++;
- Coutput << "State Pattern." << endl;
- Coutput << entry -> from -> Utf8Name()
- << " is the Context class."
- << endl
- << entry -> to -> Utf8Name()
- << " is the State interface."
- << endl;
- Coutput << "Concrete State classes: ";
- entry->to->subtypes->Print();
- Coutput << "Delegation through "
- << vsym -> Utf8Name()
- << " of type "
- << vsym -> Type() -> Utf8Name()
- << endl
- << dsym -> Utf8Name()
- << " changes the state variable "
- << vsym -> Utf8Name()
- << endl;
- Coutput << dsym->Utf8Name()
- << " is invoked by ";
- dsym->callers->Print();
- Coutput << "File Location: "
- << entry -> from -> file_symbol -> FileName()
- << ",\n "
- << entry -> to -> file_symbol -> FileName()
- << endl
- << endl;
- }
- else
- {
- nStrategy++;
- Coutput << "Strategy Pattern." << endl;
- Coutput << entry -> from -> Utf8Name()
- << " is the Context class."
- << endl
- << entry -> to -> Utf8Name()
- << " is the Strategy interface."
- << endl;
- Coutput << "Concrete Strategy classes: ";
- entry->to->subtypes->Print();
- Coutput << "Delegation through "
- << vsym -> Utf8Name()
- << " of type "
- << vsym -> Type() -> Utf8Name()
- << endl
- << "File Location: "
- << entry -> from -> file_symbol -> FileName()
- << ",\n "
- << entry -> to -> file_symbol -> FileName()
- << endl
- << endl;
- }
- }
- }
- }
- }
- }
- }
- void FindStrategy1(ClassSymbolTable *cs_table, DelegationTable *d_table, WriteAccessTable *w_table, ReadAccessTable *r_table, MethodSymbolTable *ms_table)
- {
- multimap<TypeSymbol*,TypeSymbol*> cache;
- unsigned c;
- for (c = 0; c < cs_table->size(); c++)
- {
- TypeSymbol *context = (*cs_table)[c];
- if (!context->ACC_ABSTRACT() && !context->Anonymous() && (!context->subtypes || !context->subtypes->Size()))
- {
- for (unsigned i = 0; i < context->NumVariableSymbols(); i++)
- {
- VariableSymbol *vsym = context->VariableSym(i);
- if (vsym->Type()->file_symbol
- && vsym->Type()->file_symbol->IsJava()
- && vsym->Type()->ACC_ABSTRACT()
- && !vsym->Type()->IsFamily(context)
- && !vsym->Type()->IsArray()
- //&& !vsym->Type()->IsSelfContaining()
- )
- {
- MethodSymbol *dsym = NULL;
- multimap<VariableSymbol*, MethodSymbol*>::iterator p;
- bool flag = false;
- for (p = w_table->begin(); !dsym && p!=w_table->end();p++)
- {
- //VariableSymbol *t1 = p->first;
- //MethodSymbol *t2 = p->second;
- if (p->first==vsym)
- {
- flag = true;
- if (p->second->declaration
- && p->second->declaration->MethodDeclarationCast()
- && Connectivity(p->second, vsym->Type(), ms_table))
- dsym = p->second;
- }
- }
- if (dsym)
- {
- nState++;
- Coutput << "State Pattern." << endl;
- Coutput << context->Utf8Name() << " is the Context class." << endl
- << vsym->Type()->Utf8Name() << " is the State interface." << endl;
- Coutput << "Concrete State classes: ";
- vsym->Type()->subtypes->Print();
- Coutput << "Delegation through " << vsym->Utf8Name() << " of type " << vsym->Type()->Utf8Name() << endl
- << dsym->Utf8Name() << " changes the state variable " << vsym->Utf8Name() << endl;
- Coutput << dsym->Utf8Name() << " is invoked by ";
- dsym->invokers->Print();
- Coutput << "File Location: "
- << context->file_symbol->FileName() << ",\n "
- << vsym->Type()->file_symbol->FileName()
- << endl
- << endl;
- }
- else if (flag)
- {
- nStrategy++;
- Coutput << "Strategy Pattern." << endl;
- Coutput << context->Utf8Name() << " is the Context class." << endl
- << vsym->Type()->Utf8Name() << " is the Strategy interface." << endl;
- Coutput << "Concrete Strategy classes: ";
- vsym->Type()->subtypes->Print();
- Coutput << "Delegation through " << vsym->Utf8Name() << " of type " << vsym->Type()->Utf8Name() << endl;
- Coutput << "File Location: "
- << context->file_symbol->FileName() << ",\n "
- << vsym->Type()->file_symbol->FileName()
- << endl
- << endl;
- }
-
- }
- }
- }
- }
- }
- void FindComposite(ClassSymbolTable *cs_table, DelegationTable *d_table)
- {
- unsigned c;
- for (c = 0; c < cs_table -> size(); c++)
- {
- if (!(*cs_table)[c] -> ACC_ABSTRACT() && (*cs_table)[c]->supertypes_closure && (*cs_table)[c]->supertypes_closure->Size())
- {
- TypeSymbol *unit_type = (*cs_table)[c];
- AstClassBody* class_body = unit_type -> declaration;
- for (unsigned i = 0; i < class_body -> NumInstanceVariables(); i++)
- {
- AstFieldDeclaration* field_decl = class_body -> InstanceVariable(i);
- for (unsigned vi = 0; (vi < field_decl -> NumVariableDeclarators()); vi++)
- {
- AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
- ContainerType *container_type = Utility::IdentifyContainerType(vd->symbol);
- //TypeSymbol *contained_type = unit_type->IsOnetoMany(vd->symbol, d_table);
- if (!container_type)
- break;
-
- if (container_type->kind == ContainerType::ARRAY)
- {
- if ((unit_type != vd->symbol->Type()->base_type)
- && unit_type -> IsSubtype(vd->symbol->Type()->base_type))
- {
- nComposite++;
- Coutput << "Composite Pattern." << endl;
- Coutput << unit_type->Utf8Name() << " is the composite class." << endl;
- Coutput << vd->symbol->Utf8Name() << " is the composite instance." << endl;
- Coutput << vd->symbol->Type()->base_type->Utf8Name() << " is the component class." << endl;
- Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl;
- if (vd->symbol->Type()->base_type->file_symbol->IsClassOnly() && getenv("PINOT_HOME"))
- Coutput << "$PINOT_HOME/lib/rt.jar" << vd->symbol->Type()->base_type->fully_qualified_name->value << ".class" << endl << endl;
- else
- Coutput << "File Location: " << vd->symbol->Type()->base_type->file_symbol->FileName() << endl << endl;
- }
- }
- else
- {
- SymbolSet set;
- set.Union(*unit_type->supertypes_closure);
- int ct = 0;
- for (int i = 0; i < d_table -> size(); i++)
- {
- DelegationEntry *entry = d_table -> Entry(i);
- if (entry->vsym
- && (entry->vsym == vd->symbol)
- && container_type->IsPutMethod(entry->call->symbol->MethodCast()))
- {
- TypeSymbol *type = container_type->GetPutType(entry->call);
- if (type && type->supertypes_closure)
- {
- type->supertypes_closure->AddElement(type);
- set.Intersection(*type->supertypes_closure);
- type->supertypes_closure->RemoveElement(type);
- ct++;
- }
- }
- }
- if (ct == 0)
- break;
- //remove java/lang/Object from set
- Utility::RemoveBuiltinInterfaces(set);
- if (set.Size() == 0)
- break;
- nComposite++;
- Coutput << "Composite pattern." << endl;
- Coutput << unit_type->Utf8Name() << " is the composite class." << endl;
- Coutput << vd->symbol->Utf8Name() << " is the composite instance." << endl;
- Coutput << set.FirstElement()->TypeCast()->Utf8Name() << " is the component class." << endl;
- Coutput << "File Location: " << unit_type->file_symbol->FileName() << endl;
- Coutput << "File Location: " << set.FirstElement()->TypeCast()->file_symbol->FileName() << endl << endl;
-
- /*
- if ((contained_type != unit_type) && contained_type && unit_type -> IsSubtype(contained_type))
- {
- nComposite++;
- Coutput << "Composite pattern." << endl;
- Coutput << unit_type -> Utf8Name() << " is the composite class." << endl;
- Coutput << vd -> symbol -> Utf8Name() << " is the composite instance." << endl;
- Coutput << contained_type -> Utf8Name() << " is the component class." << endl;
- Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl;
- Coutput << "File Location: " << contained_type -> file_symbol -> FileName() << endl << endl;
- }
- */
- }
- delete container_type;
- }
- }
- }
- }
- }
- void FindMediator(ClassSymbolTable *cs_table, DelegationTable *d_table)
- {
- unsigned c;
- for (c = 0; c < cs_table -> size(); c++)
- {
- TypeSymbol *unit_type = (*cs_table)[c];
- if (!unit_type -> ACC_INTERFACE()
- && !unit_type -> IsInner()
- && !unit_type -> ACC_PRIVATE())
- {
- SymbolSet colleagues;
- SymbolSet observers;
- SymbolSet *dset = unit_type -> references;
- Symbol *sym = (dset) ? dset->FirstElement() : NULL;
- while (sym)
- {
- TypeSymbol *type = sym -> TypeCast();
- if (!type->Primitive()
- && type -> ACC_ABSTRACT()
- && !type -> ACC_INTERFACE()
- && type -> references
- && (unit_type != type)
- && type -> file_symbol-> IsJava()
- && type -> references -> IsElement(unit_type)
- && unit_type -> IsOnetoMany(type))
- {
- if (d_table -> IsBidirectional(unit_type, type) == 3)
- colleagues.AddElement(type);
- else if (d_table -> IsBidirectional(unit_type, type) > 0)
- observers.AddElement(type);
- }
- sym = dset->NextElement();
- }
- if (!colleagues.IsEmpty())
- {
- nMediator++;
- Coutput << "Mediator pattern." << endl;
- Coutput << unit_type -> Utf8Name() << " is a Mediator class." << endl;
- Symbol *sym = NULL;
- Coutput << "Colleagues: ";
- sym = colleagues.FirstElement();
- while (sym)
- {
- Coutput << sym -> TypeCast() -> Utf8Name() << " ";
- sym = colleagues.NextElement();
- }
- Coutput << endl;
- Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl << endl;
- colleagues.SetEmpty();
- }
- else if (!observers.IsEmpty())
- {
- nObserver++;
- Coutput << "Observer pattern." << endl;
- Coutput << unit_type -> Utf8Name() << " is a Subject class." << endl;
- Symbol *sym = NULL;
- Coutput << "Observers: ";
- sym = observers.FirstElement();
- while (sym)
- {
- Coutput << sym -> TypeCast() -> Utf8Name() << " ";
- sym = observers.NextElement();
- }
- Coutput << endl;
- Coutput << "File Location: " << unit_type -> file_symbol -> FileName() << endl << endl;
- observers.SetEmpty();
- }
- }
- }
- }
- bool IsJavaContainer(VariableSymbol *vsym)
- {
- if (strcmp(vsym->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
- return true;
- if (vsym->Type()->supertypes_closure)
- {
- Symbol *sym = vsym->Type()->supertypes_closure->FirstElement();
- while (sym)
- {
- TypeSymbol *type = sym->TypeCast();
- if (strcmp(type->fully_qualified_name->value, "java/util/Iterator") == 0)
- return true;
- sym = vsym->Type()->supertypes_closure->NextElement();
- }
- }
- return false;
- }
- VariableSymbol *IteratorVar(AstExpression *expression)
- {
- /*
- 1 - java.util.Iterator
- 2 - array index
- 3 - recursion
- */
- AstExpression *resolved = Utility::RemoveCasting(expression);
- if (resolved->kind == Ast::CALL)
- {
- AstMethodInvocation *call = resolved->MethodInvocationCast();
- if (call->base_opt
- && call->base_opt->symbol->VariableCast()
- && IsJavaContainer(call->base_opt->symbol->VariableCast())
- && (strcmp(call->symbol->MethodCast()->Utf8Name(), "next") == 0))
- return call -> base_opt -> NameCast() -> symbol -> VariableCast();
- }
- else if (resolved -> kind == Ast::ARRAY_ACCESS)
- {
- if (resolved -> ArrayAccessCast()->base-> kind == Ast::NAME)
- return resolved -> ArrayAccessCast()->base->symbol->VariableCast();
- }
- else if ((resolved->kind == Ast::NAME) && (resolved->NameCast()->symbol->Kind()==Symbol::VARIABLE))
- {
- return resolved->NameCast()->symbol ->VariableCast();
- }
- return 0;
- }
- VariableSymbol *ListVar(VariableSymbol *vsym)
- {
- if (!vsym->declarator->variable_initializer_opt
- || !vsym->declarator->variable_initializer_opt->ExpressionCast())
- return NULL;
- AstExpression *var_initializer = Utility::RemoveCasting(vsym->declarator->variable_initializer_opt->ExpressionCast());
-
- // vsym -> IsLocal()
- // vsym is an iterator that implements java.util.Iterator
- if (strcmp( vsym->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
- {
- if (vsym -> declarator -> variable_initializer_opt -> kind == Ast::CALL)
- {
- AstMethodInvocation *init_call = vsym -> declarator -> variable_initializer_opt -> MethodInvocationCast();
- // iterator initialized at declaration
- if (strcmp(init_call -> symbol -> MethodCast() -> Utf8Name(), "iterator") == 0)
- return (init_call->base_opt->symbol->Kind() == Symbol::VARIABLE)
- ? init_call->base_opt->symbol->VariableCast()
- : 0;
- // iterator initialized later in an assignment statement
- // vsym->owner is a Symbol, but if vsym is local then the owner is a MethodSymbol
- // verify assignment statement
- // if vsym is not local (which should be rare), and is initialized somewhere else (e.g. in other methods, also rare)
- }
- }
- else if (strcmp( vsym->Type()->fully_qualified_name->value, "java/util/ListIterator") == 0)
- {
- if (vsym -> declarator -> variable_initializer_opt -> kind == Ast::CALL)
- {
- AstMethodInvocation *init_call = vsym -> declarator -> variable_initializer_opt -> MethodInvocationCast();
- // iterator initialized at declaration
- if (strcmp(init_call -> symbol -> MethodCast() -> Utf8Name(), "listIterator") == 0)
- return init_call -> base_opt -> NameCast() -> symbol -> VariableCast();
- // iterator initialized later in an assignment statement
- // vsym->owner is a Symbol, but if vsym is local then the owner is a MethodSymbol
- // verify assignment statement
- // if vsym is not local (which should be rare), and is initialized somewhere else (e.g. in other methods, also rare)
- }
- }
- else if ((vsym->declarator->variable_initializer_opt->kind == Ast::NAME)
- && (vsym->declarator->variable_initializer_opt->NameCast()->symbol->Kind()==Symbol::VARIABLE))
- {
- return vsym->declarator->variable_initializer_opt->NameCast()->symbol->VariableCast();
- }
- else if (var_initializer->kind == Ast::CALL)
- {
- AstMethodInvocation *init_call = var_initializer->MethodInvocationCast();
- if (init_call->base_opt && init_call->base_opt->symbol->VariableCast())
- {
- if (((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/Vector") == 0)
- && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "elementAt") == 0))
- || ((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/ArrayList") == 0)
- && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "get") == 0))
- )
- return init_call->base_opt->symbol->VariableCast();
- else if ((strcmp(init_call->base_opt->symbol->VariableCast()->Type()->fully_qualified_name->value, "java/util/Iterator") == 0)
- && (strcmp(init_call->symbol->MethodCast()->Utf8Name(), "next") == 0))
- {
- VariableSymbol *iterator = init_call->base_opt->symbol->VariableCast();
- AstMethodInvocation *i_init_call = iterator->declarator->variable_initializer_opt->MethodInvocationCast();
- // iterator initialized at declaration
- if (strcmp(i_init_call->symbol->MethodCast()->Utf8Name(), "iterator") == 0)
- return i_init_call->base_opt->symbol->VariableCast();
- }
- }
-
- }
- return NULL;
- }
- void FindObserver(ClassSymbolTable *cs_table, DelegationTable *d_table)
- {
- vector<TypeSymbol*> cache;
- unsigned c;
- for (c = 0; c < cs_table ->size(); c++)
- {
- TypeSymbol *unit_type = (*cs_table)[c];
- if (!unit_type -> ACC_INTERFACE())
- {
- for (unsigned i = 0; i < unit_type -> declaration-> NumInstanceVariables(); i++)
- {
- AstFieldDeclaration* field_decl = unit_type -> declaration -> InstanceVariable(i);
- for (unsigned vi = 0; vi < field_decl -> NumVariableDeclarators(); vi++)
- {
- AstVariableDeclarator* vd = field_decl -> VariableDeclarator(vi);
- TypeSymbol *generic_type = unit_type -> IsOnetoMany(vd -> symbol, d_table) ;
- if (generic_type && generic_type -> file_symbol)
- {
- for (int j = 0; j < d_table -> size(); j++)
- {
- DelegationEntry* entry = d_table -> Entry(j);
- if ((unit_type == entry -> enclosing -> containing_type) && (generic_type == entry -> to))
- {
- /*
- if ((unit_type == generic_type) && (entry -> vsym == vd -> symbol) && (entry -> enclosing == entry -> method) && (entry -> enclosing -> callers -> Size() > 1))
- {
- nObserver++;
- Coutput << "Observer Pattern." << endl
- << unit_type -> Utf8Name() << " is an observer iterator." << endl
- << generic_type -> Utf8…
Large files files are truncated, but you can click here to view the full file