public override bool test(CSsemi.CSemiExp semi) { Display.displayRules(actionDelegate, "rule DetectFunction"); if (semi[semi.count - 1] != "{") { return(false); } int index = semi.FindFirst("("); if (index > 0 && !isSpecialToken(semi[index - 1])) { Repository rep = Repository.getInstance(); CSsemi.CSemiExp local = new CSsemi.CSemiExp(); local.Add("function").Add(semi[index - 1]); doActions(local); if (!rep.isFirstPass) { ///////////////////////////////////////////////////////////////// // // Parse function parameters to look for class dependencies // ///////////////////////////////////////////////////////////////// CSsemi.CSemiExp parameters = TokenHelper.GetFunctionParameters(semi); for (int i = 0; i < TokenHelper.GetNumberOfParameters(parameters); i++) { parameters = TokenHelper.RemoveNewLines(parameters); parameters = TokenHelper.RemoveIndicies(parameters); parameters = TokenHelper.RemoveGenerics(parameters); List <string> l = TokenHelper.GetFunctionParameterAtIndex(parameters, i); foreach (CClassInfo ci in rep.parsedData.classList) { if (semi.Contains(ci.className) != -1) { if (rep.stack.count < 2) { break; } string ns = rep.stack[0].name; // namespace string cl = rep.stack[1].name; // class string fn = rep.stack[rep.stack.count - 1].name; // function CClassInfo currentClassInfo = rep.parsedData.getClassInfo(cl); CFunctionInfo currentFunctioninfo = rep.parsedData.getClassFunctionInfo(cl, fn); currentFunctioninfo.addDependency(l[l.Count - 2]); } } } } return(true); } return(false); }
//----< calculate cohesion using class data members and function data member references >------------------------------------ public static int calculateCohesion(CClassInfo classInfo) { int cohesionValue = 0; bool found; foreach (CFunctionInfo functionInfoA in classInfo.functionInfoList) { found = false; foreach (CFunctionInfo functionInfoB in classInfo.functionInfoList) { if (functionInfoA.name == functionInfoB.name) { found = true; continue; } if (found) { //Console.WriteLine("comparing {0} {1}", functionInfoA.name, functionInfoB.name); if (!doMembersShareValues(functionInfoA.dataMemberReferences, functionInfoB.dataMemberReferences)) { //Console.WriteLine("--- don't share {0} {1}", functionInfoA.name, functionInfoB.name); cohesionValue++; } } } } return(cohesionValue); }
//----< show formatted analysis output >----------------- static void showOutput() { Repository rep = Repository.getInstance(); List <Elem> table = rep.locations; Console.WriteLine(); Console.WriteLine( " {0,13} {1,24} {2,5} {3,5} {4,5} {5,5} {6,5}", "category", "name", "loc", "cmplx", "cohsn", "coupl", "main" ); Console.WriteLine( " {0,13} {1,24} {2,5} {3,5} {4,5} {5,5} {6,5}", "--------", "----", "---", "-----", "-----", "-----", "-----" ); foreach (Elem e in table) { bool isClass = false; int locValue = optLOC ? optLOCCoefficient * (e.endLine - e.beginLine + 1) : 0; int complexityValue = optComplexity ? optComplexityCoefficient * (e.endScopeCount - e.beginScopeCount + 1) : 0; int couplingValue = 0; int cohesionValue = 0; int mainIndex = 0; if (e.type == "class" || e.type == "struct") { isClass = true; CClassInfo classInfo = rep.parsedData.getClassInfo(e.name); couplingValue = optCoupling ? optCouplingCoefficient * CCalculateMetrics.calculateCoupling(classInfo) : 0; cohesionValue = optCohesion ? optCohesionCoefficient * CCalculateMetrics.calculateCohesion(classInfo) : 0; mainIndex = locValue + complexityValue + couplingValue + cohesionValue; Console.WriteLine(); } Console.WriteLine( " {0,13} {1,24} {2,5} {3,5} {4,5} {5,5} {6,5}", e.type, e.name, optLOC ? locValue.ToString() : string.Empty, optComplexity ? complexityValue.ToString() : string.Empty, optCohesion ? (isClass ? cohesionValue.ToString() : string.Empty) : string.Empty, optCoupling ? (isClass ? couplingValue.ToString() : string.Empty) : string.Empty, isClass ? mainIndex.ToString() : string.Empty ); totalLOC += locValue; totalComplexity += complexityValue; totalCohesion += cohesionValue; totalCoupling += couplingValue; totalMainIndex += mainIndex; } }
//----< compute coupling using class and function dependencies >------------------------------------ public static int calculateCoupling(CClassInfo classInfo) { List <string> uniqueDependencies = new List <string>(classInfo.dependencies); foreach (CFunctionInfo functionInfo in classInfo.functionInfoList) { foreach (string s in functionInfo.dependencies) { if (!uniqueDependencies.Contains(s)) { uniqueDependencies.Add(s); } } } return(uniqueDependencies.Count); }
//----< find the class using the class name >------------------------------------ public CClassInfo getClassInfo(string className) { foreach (CClassInfo ci in classList) { if (ci.className == className) { return(ci); } } // allocate a new one CClassInfo newClassInfo = new CClassInfo(); newClassInfo.className = className; classList.Add(newClassInfo); return(newClassInfo); }
//----< get function info for a particular class >------------------------------------ public CFunctionInfo getClassFunctionInfo(string className, string classFunction) { CClassInfo classInfo = getClassInfo(className); foreach (CFunctionInfo fi in classInfo.functionInfoList) { if (fi.name == classFunction) { return(fi); } } // allocate a new one CFunctionInfo newFunctionInfo = new CFunctionInfo(); newFunctionInfo.name = classFunction; classInfo.functionInfoList.Add(newFunctionInfo); return(newFunctionInfo); }
//----< Test Stub >-------------------------------------------------- #if (TEST_PARSER) static void Main(string[] args) { Console.Write("\n Demonstrating Parser"); Console.Write("\n ======================\n"); ShowCommandLine(args); Parser parser; List <string> files = TestParser.ProcessCommandline(args); BuildCodeAnalyzer builder = null; foreach (string file in files) { Console.Write("\n Processing file {0}\n", System.IO.Path.GetFileName(file)); CSsemi.CSemiExp semi = new CSsemi.CSemiExp(); semi.displayNewLines = false; if (!semi.open(file as string)) { Console.Write("\n Can't open {0}\n\n", args[0]); return; } Console.Write("\n Type and Function Analysis"); Console.Write("\n ----------------------------"); builder = new BuildCodeAnalyzer(semi); parser = builder.build(true); try { while (semi.getSemi()) { parser.parse(semi); } Console.Write("\n locations table contains:"); } catch (Exception ex) { Console.Write("\n\n {0}\n", ex.Message); } Repository rep = Repository.getInstance(); List <Elem> table = rep.locations; Console.Write( "\n {0,10}, {1,25}, {2,5}, {3,5}, {4,5}, {5,5}, {6,5}, {7,5}", "category", "name", "bLine", "eLine", "bScop", "eScop", "size", "cmplx" ); Console.Write( "\n {0,10}, {1,25}, {2,5}, {3,5}, {4,5}, {5,5}, {6,5}, {7,5}", "--------", "----", "-----", "-----", "-----", "-----", "----", "-----" ); foreach (Elem e in table) { if (e.type == "class" || e.type == "struct") { Console.Write("\n"); } Console.Write( "\n {0,10}, {1,25}, {2,5}, {3,5}, {4,5}, {5,5}, {6,5}, {7,5}", e.type, e.name, e.beginLine, e.endLine, e.beginScopeCount, e.endScopeCount + 1, e.endLine - e.beginLine + 1, e.endScopeCount - e.beginScopeCount + 1 ); } Console.Write("\n"); semi.close(); } foreach (string file in files) { Console.Write("\n Processing file {0}\n", System.IO.Path.GetFileName(file)); CSsemi.CSemiExp semi = new CSsemi.CSemiExp(); semi.displayNewLines = false; if (!semi.open(file as string)) { Console.Write("\n Can't open {0}\n\n", args[0]); return; } Console.Write("\n Type and Function Analysis"); Console.Write("\n ----------------------------"); builder = new BuildCodeAnalyzer(semi); parser = builder.build(false); try { while (semi.getSemi()) { parser.parse(semi); } Console.Write("\n locations table contains:"); } catch (Exception ex) { Console.Write("\n\n {0}\n", ex.Message); } Repository rep = Repository.getInstance(); List <Elem> table = rep.locations; Console.Write( "\n {0,10}, {1,25}, {2,5}, {3,5}, {4,5}, {5,5}, {6,5}, {7,5}", "category", "name", "bLine", "eLine", "bScop", "eScop", "size", "cmplx" ); Console.Write( "\n {0,10}, {1,25}, {2,5}, {3,5}, {4,5}, {5,5}, {6,5}, {7,5}", "--------", "----", "-----", "-----", "-----", "-----", "----", "-----" ); foreach (Elem e in table) { if (e.type == "class" || e.type == "struct") { Console.Write("\n"); } Console.Write( "\n {0,10}, {1,25}, {2,5}, {3,5}, {4,5}, {5,5}, {6,5}, {7,5}", e.type, e.name, e.beginLine, e.endLine, e.beginScopeCount, e.endScopeCount + 1, e.endLine - e.beginLine + 1, e.endScopeCount - e.beginScopeCount + 1 ); if (e.type == "class" || e.type == "struct") { CClassInfo classInfo = rep.parsedData.getClassInfo(e.name); Console.WriteLine("Coupling: {0}", CCalculateMetrics.calculateCoupling(classInfo)); Console.WriteLine("Cohesion: {0}", CCalculateMetrics.calculateCohesion(classInfo)); } } Console.Write("\n"); semi.close(); } Console.Write("\n\n"); }
static void Main(string[] args) { CClassList classList = new CClassList(); CClassInfo classInfo = new CClassInfo(); classList.classList.Add(classInfo); // CLASS B classInfo.className = "CTestClassA"; classInfo.dependencies.Add("cdCToken"); classInfo.dependencies.Add("cdITem"); classInfo.dependencies.Add("cdString"); CMemberInfo memberInfo = new CMemberInfo(); memberInfo.type = "cmA"; memberInfo.name = "nameA"; classInfo.dataMembers.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "cmB"; memberInfo.name = "nameB"; classInfo.dataMembers.Add(memberInfo); // FUNCTION A CFunctionInfo functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction1"; memberInfo = new CMemberInfo(); memberInfo.type = "cmA"; memberInfo.name = "nameA"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "cmB"; memberInfo.name = "nameB"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); // FUNCTION B functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction2"; memberInfo = new CMemberInfo(); memberInfo.type = "cmZ"; memberInfo.name = "newItemA"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "cmB"; memberInfo.name = "nameB"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); // FUNCTION C functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction3"; memberInfo = new CMemberInfo(); memberInfo.type = "cmB"; memberInfo.name = "nameB"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "cmJ"; memberInfo.name = "newItemB"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); classInfo = new CClassInfo(); classList.classList.Add(classInfo); // CLASS B classInfo.className = "CTestClassB"; classInfo.dependencies.Add("yellow"); classInfo.dependencies.Add("orange"); classInfo.dependencies.Add("green"); memberInfo = new CMemberInfo(); memberInfo.type = "Monkey"; memberInfo.name = "dave"; classInfo.dataMembers.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "Car"; memberInfo.name = "Toyota"; classInfo.dataMembers.Add(memberInfo); // FUNCTION A functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction1B"; memberInfo = new CMemberInfo(); memberInfo.type = "Monkey"; memberInfo.name = "dave"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "Snake"; memberInfo.name = "Python"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); // FUNCTION B functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction2B"; memberInfo = new CMemberInfo(); memberInfo.type = "Bug"; memberInfo.name = "Beatles"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "Snake"; memberInfo.name = "Python"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); // FUNCTION C functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction3B"; memberInfo = new CMemberInfo(); memberInfo.type = "Computer"; memberInfo.name = "Dell"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "Computer"; memberInfo.name = "HP"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); Console.WriteLine("Break here and observe ParsedData data structure."); }
public override bool test(CSsemi.CSemiExp semi) { Repository rep = Repository.getInstance(); if (rep.isFirstPass) { return(false); } if (rep.stack.count <= 2) { // we are not in a class or function scope return(false); } else if (rep.stack[rep.stack.count - 1].type != "function") { return(false); } else if (rep.stack.count > 3) { //Console.WriteLine("skip: unknown code block in function, unhandled"); return(false); } Display.displayRules(actionDelegate, "rule DetectFunctionMembers"); int index = semi.Contains(";"); if (index != -1) { ///////////////////////////////////////////////////////////////// // // Parse function body to look for class member references // ///////////////////////////////////////////////////////////////// if (rep.stack.count < 3) { return(false); } string ns = rep.stack[0].name; // namespace string cl = rep.stack[1].name; // class string fn = rep.stack[2].name; // function CClassInfo currentClassInfo = rep.parsedData.getClassInfo(cl); CFunctionInfo currentFunctionInfo = rep.parsedData.getClassFunctionInfo(cl, fn); foreach (CMemberInfo classDataMember in currentClassInfo.dataMembers) { if (semi.Contains(classDataMember.name) != -1) { currentFunctionInfo.addDataMemberReference(classDataMember.type, classDataMember.name); } } ///////////////////////////////////////////////////////////////// // // Parse function body to look for class dependencies // ///////////////////////////////////////////////////////////////// foreach (CClassInfo ci in rep.parsedData.classList) { if (semi.Contains(ci.className) != -1) { currentFunctionInfo.addDependency(ci.className); } } return(true); } return(false); }
public override bool test(CSsemi.CSemiExp semi) { Repository rep = Repository.getInstance(); //if (!rep.isFirstPass) //{ //return false; //} if (rep.stack.count <= 0) { // we are not in a class or function scope return(false); } else if (rep.stack[rep.stack.count - 1].type != "class") { return(false); } else if (rep.stack.count > 2) { //Console.WriteLine("skip: found class in a class, unhandled"); return(false); } Display.displayRules(actionDelegate, "rule DetectClassMembers"); int index = semi.Contains(";"); if (index != -1) { CSsemi.CSemiExp clean = TokenHelper.RemoveNewLines(semi); clean = TokenHelper.GetLeftOfEqual(clean); clean = TokenHelper.RemoveGenerics(clean); clean = TokenHelper.RemoveIndicies(clean); clean = TokenHelper.RemoveKeywords(clean); clean = TokenHelper.RemoveAccess(clean); clean = TokenHelper.CombineNamespace(clean); // "if", "for", "foreach", "while", "catch", "using" if ((clean[0] == "using") || (clean[0] == "return") || (clean[0] == "if") || (clean[0] == "for") || (clean[0] == "break") || (clean.Contains("(") != -1) || (clean[0] == "get") || (clean[0] == "set")) { return(false); } CSsemi.CSemiExp local = new CSsemi.CSemiExp(); // create local semiExp with tokens for type and name local.displayNewLines = false; if (rep.stack.count < 2) { return(false); } string ns = rep.stack[0].name; string cl = rep.stack[1].name; if (clean.count >= 2) { local.Add(clean[0]).Add(clean[1]); if (rep.isFirstPass) { ///////////////////////////////////////////////////////////////// // // Parse Class to get class members // ///////////////////////////////////////////////////////////////// if (rep.stack.count == 2) { string type = clean[0]; string name = clean[1]; CClassInfo currentClassInfo = rep.parsedData.getClassInfo(cl); currentClassInfo.addDataMember(type, name); } } else { ///////////////////////////////////////////////////////////////// // // Parse Class body to detect class use dependency // ///////////////////////////////////////////////////////////////// if (rep.stack.count == 2) { foreach (CClassInfo ci in rep.parsedData.classList) { if (semi.Contains(ci.className) != -1) { CClassInfo currentClassInfoList = rep.parsedData.getClassInfo(cl); currentClassInfoList.addDependency(ci.className); } } } } return(true); } } return(false); }
public override bool test(CSsemi.CSemiExp semi) { Display.displayRules(actionDelegate, "rule DetectClass"); int indexCL = semi.Contains("class"); int indexIF = semi.Contains("interface"); int indexST = semi.Contains("struct"); int index = Math.Max(indexCL, indexIF); index = Math.Max(index, indexST); if (index != -1) { ///////////////////////////////////////////////////////////////// // // Parse Class to get class names // ///////////////////////////////////////////////////////////////// Repository rep = Repository.getInstance(); CSsemi.CSemiExp local = new CSsemi.CSemiExp(); // local semiExp with tokens for type and name local.displayNewLines = false; local.Add(semi[index]).Add(semi[index + 1]); doActions(local); if (rep.stack.count < 2) { return(false); } string ns = rep.stack[0].name; string cl = rep.stack[1].name; // If it's not there, it's automatically added in getClassInfo() CClassInfo currentClassInfo = rep.parsedData.getClassInfo(cl); ///////////////////////////////////////////////////////////////// // // Parse Class to detect inheritance // ///////////////////////////////////////////////////////////////// if (!rep.isFirstPass) { index = semi.Contains(":"); if (index != -1) { if (index + 1 < semi.count) { string baseClass = semi[index + 1]; currentClassInfo.addDependency(baseClass); } } } return(true); } return(false); }
static void Main(string[] args) { CClassList classList = new CClassList(); CClassInfo classInfo = new CClassInfo(); // CLASS classInfo.className = "CTestClass"; classInfo.dependencies.Add("cdCToken"); classInfo.dependencies.Add("cdITem"); classInfo.dependencies.Add("cdString"); CMemberInfo memberInfo = new CMemberInfo(); memberInfo.type = "cmA"; memberInfo.name = "nameA"; classInfo.dataMembers.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "cmB"; memberInfo.name = "nameB"; classInfo.dataMembers.Add(memberInfo); // FUNCTION A CFunctionInfo functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction1"; memberInfo = new CMemberInfo(); memberInfo.type = "cmA"; memberInfo.name = "nameA"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "cmB"; memberInfo.name = "nameB"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); // FUNCTION B functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction2"; memberInfo = new CMemberInfo(); memberInfo.type = "cmZ"; memberInfo.name = "newItemA"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "cmB"; memberInfo.name = "nameB"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); // FUNCTION C functionInfo = new CFunctionInfo(); functionInfo.name = "fnTestFunction3"; memberInfo = new CMemberInfo(); memberInfo.type = "cmB"; memberInfo.name = "nameB"; functionInfo.dataMemberReferences.Add(memberInfo); memberInfo = new CMemberInfo(); memberInfo.type = "cmJ"; memberInfo.name = "newItemB"; functionInfo.dataMemberReferences.Add(memberInfo); classInfo.functionInfoList.Add(functionInfo); int cohesion = calculateCohesion(classInfo); int coupling = calculateCoupling(classInfo); Console.WriteLine("cohesion {0}, coupling {1}", cohesion, coupling); }