#include #include #include #include #include "Command.h" #include "GraphManager.h" using std::cout; using std::endl; void BuildGraphCommand::printTypeInfo( Container::const_iterator ptr) { cout << "\t\tvar: " << ptr->getName() << "\ttype: " << ptr->getType().getName() << "\tcategory: " << ptr->getType().getCategory().value() << "\tcategory,name: " << ptr->getType().getCategory().getName() << "\tgetSignature: " << ptr->getType().getCategory().getSignature() << endl; } bool BuildGraphCommand::isTemplate( const string & src ) const { return ( src.find('<', 0) < src.size() ); } void BuildGraphCommand::printCinfoPtr() const { vector< Container::const_iterator >::const_iterator ptr = cinfoPtr.begin(); cout << "Classes in cinfoPtr: " << endl; for ( ; ptr != cinfoPtr.end(); ++ptr) { cout << "\t" << (*ptr)->getName() << endl; } } void BuildGraphCommand::addEdge(const Edge& edge) { int rc; if ( edge.getType() != "header" ) { if ( (!isTemplate(edge.getSrc()) && !GraphManager::Instance()->isClass(edge.getSrc())) || (!isTemplate(edge.getDest()) && !GraphManager::Instance()->isClass(edge.getDest())) ) { return; // probably an enum or typedef (ugh!) } } Graph& graph = GraphManager::Instance()->getGraph(); if ( edge.getType() == "header" ) { graph.insert( Node(edge.getSrc(), "header", 1, 0) ); } else { rc = graph.addEdge(edge); if (rc == 1) GraphManager::Instance()->incrIndegree(edge.getDest()); } } void BuildGraphCommand::checkForPolymorphicEdges(const string& source, const string& target) { vector< Container::const_iterator >::const_iterator ptr = std::find_if(cinfoPtr.begin(), cinfoPtr.end(), SearchClassJar(target)); if ( ptr == cinfoPtr.end() ) { cout << "ERROR: " << target << " NOT FOUND" << endl; return; } Container::const_iterator cinfo_ptr = *ptr; const Container kids_container = cinfo_ptr->children(); for ( Container::const_iterator kid = kids_container.begin(); kid != kids_container.end(); ++kid ) { addEdge(Edge(source, kid->getName(), "polymorphic")); checkForPolymorphicEdges(source, kid->getName()); } } void BuildGraphCommand::doNestedClassInfo( const string& class_name, const Container& nestedClasses) { for ( Container::const_iterator ptr = nestedClasses.begin(); ptr != nestedClasses.end(); ++ptr ) { ++nestedClassCount; string edge_name = ptr->getName(); GraphManager::Instance()->addClassToClassList(ptr->getName()); // FOR NOW, CHECKING FOR TEMPLATE CLASS W/ No. Params: if ( ptr->templateParameters().size() > 0 ) { continue; } addEdge(Edge(class_name, edge_name, "ownedElement")); } buildClasses(nestedClasses); } void BuildGraphCommand::processFunctionLocals( const string& class_name, const Container& vars ) { for ( Container::const_iterator var_ptr = vars.begin(); var_ptr != vars.end(); ++var_ptr ) { //cout << "\tParam: " << var_ptr->getName() << endl; string edge_name = var_ptr->getType().getName(); int edge_type = 0; if ( var_ptr->getType().isUserDefined() ) { Container temp = var_ptr->getType().templateArguments(); edge_type = var_ptr->getType().getCategory().value(); if ( temp.size() > 0 ) { for ( Container::const_iterator it = temp.begin(); it != temp.end(); ++it ) { // ERROR: If there is more than one template argument, the // following code will only get the last one. // Also, following code doesn't get transmission mode! edge_name = var_ptr->getType().getName() + "<" + it->getName() + ">"; } } addEdge(Edge(class_name, edge_name, "dependence")); if ( edge_type == 115 ) { // Actually, 115 is for pointers and reference, but both // are polymorphic, so we need to chec! // You can use getSignature to see if it's "*" or "&": //printTypeInfo(var_ptr); checkForPolymorphicEdges(class_name, edge_name); } } } } void BuildGraphCommand::doClassFunctionInfo( const string& class_name, const Container& vars ) { for ( Container::const_iterator ptr = vars.begin(); ptr != vars.end(); ++ptr ) { //cout << "Function: " << ptr->getName() << endl; Container params = ptr->params(); processFunctionLocals(class_name, params); Container locals = ptr->localVars(); processFunctionLocals(class_name, locals); } } void BuildGraphCommand::doClassVariableInfo( const string& class_name, const Container& vars ) { for ( Container::const_iterator ptr = vars.begin(); ptr != vars.end(); ++ptr ) { if ( ptr->getType().isUserDefined() ) { Container temp = ptr->getType().templateArguments(); string edge_name = ptr->getType().getName(); if ( temp.size() > 0 ) { // It's a template instance variable; change edge_name for ( Container::const_iterator it = temp.begin(); it != temp.end(); ++it ) { string mode = it->getCategory().getSignature(); edge_name = ptr->getType().getName() + "<" + it->getName() + mode + ">"; addEdge(Edge(edge_name, "", "header")); //cout << "Template for " << class_name << ": " //<< edge_name << endl; int edge_type = it->getCategory().value(); if ( it->isUserDefined() ) { addEdge(Edge(edge_name, it->getName(), EdgeType::convertToString(static_cast(edge_type)))); if ( edge_type == 115 ) { checkForPolymorphicEdges(edge_name, it->getName()); } } } } int edge_type = ptr->getType().getCategory().value(); addEdge(Edge(class_name, edge_name, EdgeType::convertToString(static_cast(edge_type)))); if ( edge_type == 115 ) { // I don't think this will add polymorphic edges if the // target(edge_name) is a template instance -- need ASG! checkForPolymorphicEdges(class_name, edge_name); } } } } void BuildGraphCommand::buildClasses( const Container& classes) { // Have to put all of the classes in a list first, // so that they're there when they are processed later: for ( Container::const_iterator cinfo_ptr = classes.begin(); cinfo_ptr != classes.end(); ++cinfo_ptr ) { if ( cinfo_ptr->templateParameters().size() > 0 ) { continue; // template classes are not classes! } GraphManager::Instance()->addClassToClassList(cinfo_ptr->getName()); cinfoPtr.push_back( cinfo_ptr ); //Container nestedClasses = cinfo_ptr->classDefsInClass(); //if ( nestedClasses.size() > 0 ) { //doNestedClassInfo(class_name, nestedClasses); //} } //printCinfoPtr(); for ( Container::const_iterator cinfo_ptr = classes.begin(); cinfo_ptr != classes.end(); ++cinfo_ptr ) { string class_name = cinfo_ptr->getName(); // FOR NOW, CHECKING FOR TEMPLATE CLASS W/ No. Params: if ( cinfo_ptr->templateParameters().size() > 0 ) { continue; // template classes are not classes! } // It's not a template class, so insert it addEdge(Edge(class_name, "", "header")); Container nestedClasses = cinfo_ptr->classDefsInClass(); if ( nestedClasses.size() > 0 ) { doNestedClassInfo(class_name, nestedClasses); } Container parents = cinfo_ptr->parents(); if ( parents.size() > 0 ) { for ( Container::const_iterator cinfo_ptr = parents.begin(); cinfo_ptr != parents.end(); ++cinfo_ptr ) { addEdge(Edge(class_name, cinfo_ptr->getName(), "inheritance")); } } Container vars = cinfo_ptr->dataItems(); if ( vars.size() > 0 ) { doClassVariableInfo(class_name, vars); } Container fun = cinfo_ptr->funDefsInClass(); if ( fun.size() > 0 ) { doClassFunctionInfo(class_name, fun); } } } void BuildGraphCommand::buildStuffInNamespace( const Container& nsi) { for ( Container::const_iterator ptr = nsi.begin(); ptr != nsi.end(); ++ptr ) { //cout << "Namespace: " << ptr->getName() << endl; const Container& nnsi = ptr->nameSpaceDefs(); if (nnsi.size() > 0) buildStuffInNamespace(nnsi); Container classes = ptr->classDefs(); buildClasses(classes); } } void BuildGraphCommand::execute() { Interface face(fileName); const Container& nsi = face.nameSpaces(); buildStuffInNamespace(nsi); }