// public static void PreProcessPendingObjects(KnowledgeBase KB, IOutputService output, List <KBObject> objs) { FileIniDataParser fileIniData = new FileIniDataParser(); output.Clear(); output.SelectOutput("KBDoctor"); output.StartSection("KBDoctor", "Review_Objects", "Review Objects"); InitializeIniFile(KB); IniData parsedData = fileIniData.ReadFile(KB.UserDirectory + "\\KBDoctor.ini"); string SectionName = "ReviewObject"; List <KBObject> atts = new List <KBObject>(); foreach (KBObject obj in objs) { List <KBObject> objlist = new List <KBObject>(); objlist.Add(obj); if (Utility.isRunable(obj) && !Utility.IsGeneratedByPattern(obj)) { //Check objects with parameteres without inout if (parsedData[SectionName]["ParamINOUT"].ToLower() == "true") { Objects.ParmWOInOut(objlist, output); } //Clean variables not used if (parsedData[SectionName]["CleanUnusedVariables"].ToLower() == "true") { CleanKB.CleanKBObjectVariables(obj, output); } //Check commit on exit if (parsedData[SectionName]["CheckCommitOnExit"].ToLower() == "true") { Objects.CommitOnExit(objlist, output); } //Is in module if (parsedData[SectionName]["CheckModule"].ToLower() == "true") { Objects.isInModule(objlist, output); } //With variables not based on attributes if (parsedData[SectionName]["VariablesBasedAttOrDomain"].ToLower() == "true") { Objects.ObjectsWithVarNotBasedOnAtt(objlist, output); } //Code commented if (parsedData[SectionName]["CodeCommented"].ToLower() == "true") { Objects.CodeCommented(objlist, output); } //Check complexity metrics //maxNestLevel 6 - ComplexityLevel 30 - MaxCodeBlock 500 - parametersCount 6 int maxNestLevel = 7; Int32.TryParse(parsedData[SectionName]["MaxNestLevel"], out maxNestLevel); int complexityLevel = 30; complexityLevel = Int32.Parse(parsedData[SectionName]["MaxComplexity"]); int maxCodeBlock = 500; maxCodeBlock = Int32.Parse(parsedData[SectionName]["MaxBlockSize"]); int maxParametersCount = 6; maxParametersCount = Int32.Parse(parsedData[SectionName]["MaxParameterCount"]); Objects.CheckComplexityMetrics(objlist, output, maxNestLevel, complexityLevel, maxCodeBlock, maxParametersCount); /* * Tiene todas las referencias? * Tiene calls que pueden ser UDP * Mas de un parametro de salida * Constantes en el código * Nombre "poco claro" / Descripcion "poco clara" * Si es modulo, revisar que no tenga objetos publicos no llamados * Si es modulo, revisar que no tenga objetos privados llamados desde fuera * Si es modulo, Valor de la propiedad ObjectVisibility <> Private */ } if (obj is Artech.Genexus.Common.Objects.Attribute && parsedData[SectionName]["AttributeBasedOnDomain"].ToLower() == "true") { atts.Add(obj); //Attribute Has Domain Objects.AttributeHasDomain(objlist, output); } if (obj is SDT && parsedData[SectionName]["SDTBasedAttOrDomain"].ToLower() == "true") { //SDTItems Has Domain Objects.SDTBasedOnAttDomain(objlist, output); } } if (atts.Count > 0 && parsedData[SectionName]["AttributeWithoutTable"].ToLower() == "true") { // Attributes without table Objects.AttributeWithoutTable(atts, output); } output.EndSection("KBDoctor", "Review_Objects", true); }
// public static void PreProcessPendingObjects(KnowledgeBase KB, IOutputService output, List<KBObject> objs, out List<string[]> lineswriter, out double tech_debt_total) { tech_debt_total = 0; const string KBDOCTOR_OUTPUTID = "KBDoctor"; output.SelectOutput(KBDOCTOR_OUTPUTID); FileIniDataParser fileIniData = new FileIniDataParser(); InitializeIniFile(KB); string filename = KB.UserDirectory + "\\KBDoctor.ini"; IniData parsedData = fileIniData.ReadFile(filename); string SectionName = "ReviewObject"; List<Tuple<KBObject, string, double>> recommended_list = new List<Tuple<KBObject, string, double>>(); List<KBObject> atts = new List<KBObject>(); foreach (KBObject obj in objs) { int obj_tech_debt = 0; int cant = 0; int valor = 1; string recommendations = ""; List<KBObject> objlist = new List<KBObject>(); objlist.Add(obj); if (Utility.isRunable(obj) && !Utility.IsGeneratedByPattern(obj)) { //Check objects with parameteres without inout if (CheckKeyInINI(parsedData, SectionName, "ParamINOUT", "true", "Check if all parameters have IN: OUT: INOUT: keywords", filename)) { Objects.ParmWOInOut(objlist, output, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Clean variables not used if (CheckKeyInINI(parsedData, SectionName, "CleanUnusedVariables", "true", "Remove unused variables from objects", filename)) CleanKB.CleanKBObjectVariables(obj, output, ref recommendations); //Check commit on exit if (CheckKeyInINI(parsedData, SectionName, "CheckCommitOnExit", "true", "Check if property Commit on exit = YES", filename)) { Objects.CommitOnExit(objlist, output, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Is in module if (CheckKeyInINI(parsedData, SectionName, "CheckModule", "true", "Use of modules is required", filename)) { Objects.isInModule(objlist, output, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Fix variables not based in domains or attributes bool fixvar = true; if (CheckKeyInINI(parsedData, SectionName, "FixVariables", "false", "Fix variables definition, assinging Attribute or Domain", filename)) fixvar = false; //With variables not based on attributes if (CheckKeyInINI(parsedData, SectionName, "VariablesBasedAttOrDomain", "true", "Variables must be based on Attributes or Domains", filename)) { Objects.ObjectsWithVarNotBasedOnAtt(objlist, output, fixvar, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Code commented if (CheckKeyInINI(parsedData, SectionName, "CodeCommented", "true", "Code commented is marked as error", filename)) { Objects.CodeCommented(objlist, output, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Assign types comparer if (CheckKeyInINI(parsedData, SectionName, "AssignTypes", "true", "Check if assignments have the correct Type or Domain", filename)) { AssignTypesComprarer(KB, objlist, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Parameter types comparer if (CheckKeyInINI(parsedData, SectionName, "ParameterTypes", "true", "Check if call parameters have the correct Type or Domain", filename)) { ParametersTypeComparer(KB, objlist, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Empty conditional blocks if (CheckKeyInINI(parsedData, SectionName, "EmptyConditionalBlocks", "true", "Checks if exists any IF/Else block without code in it", filename)) { EmptyConditionalBlocks(KB, objlist, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Constants in code if (CheckKeyInINI(parsedData, SectionName, "ConstantsInCode", "true", "Check if there are hardcoded constants", filename)) { ConstantsInCode(KB, objlist, out cant); obj_tech_debt += cant * valor; } //For eachs without when none if (CheckKeyInINI(parsedData, SectionName, "ForEachsWithoutWhenNone", "true", "Check if there is any 'ForEach' block without a 'When None' clause", filename)) ForEachsWithoutWhenNone(KB, objlist); //News without when duplicate if (CheckKeyInINI(parsedData, SectionName, "NewsWithoutWhenDuplicate", "true", "Check if there is any 'New' block without 'When Duplicate' clause", filename)) NewsWithoutWhenDuplicate(KB, objlist); if (CheckKeyInINI(parsedData, SectionName, "ProceduresCalledAsFuction", "true", "Check if the procedures are called as functions", filename)) { ProceduresCalledAsFunction(KB, objlist, ref recommendations, out cant); obj_tech_debt += cant * valor; } if (CheckKeyInINI(parsedData, SectionName, "DocumentsInWebPanels", "true", "Check if there are File management variables (and some others) in WebPanels", filename)) { DocumentsInWebPanels(KB, objlist, ref recommendations, out cant); obj_tech_debt += cant * valor; } //Check complexity metrics //maxNestLevel 6 - ComplexityLevel 30 - MaxCodeBlock 500 - parametersCount 6 bool aux; aux = CheckKeyInINI(parsedData, SectionName, "MaxNestLevel", "7", "Maximun nesting level allowed in source", filename); aux = CheckKeyInINI(parsedData, SectionName, "MaxComplexity", "30", "Maximun Complexity level allowed in sources", filename); aux = CheckKeyInINI(parsedData, SectionName, "MaxBlockSize", "500", "Maximun block of code", filename); aux = CheckKeyInINI(parsedData, SectionName, "MaxParameterCount", "6", "Maximun Number of parameters allowed in parm rule", filename); int maxNestLevel = 7; Int32.TryParse(parsedData[SectionName]["MaxNestLevel"], out maxNestLevel); int complexityLevel = 30; Int32.TryParse(parsedData[SectionName]["MaxComplexity"], out complexityLevel); int maxCodeBlock = 500; Int32.TryParse(parsedData[SectionName]["MaxBlockSize"], out maxCodeBlock); int maxParametersCount = 6; Int32.TryParse(parsedData[SectionName]["MaxParameterCount"], out maxParametersCount); int diffNestLevel; int diffcomplexityLevel; int diffCodeBlock; int diffParametersCount; Objects.CheckComplexityMetrics(obj, output, maxNestLevel, complexityLevel, maxCodeBlock, maxParametersCount, ref recommendations, out diffNestLevel, out diffcomplexityLevel, out diffCodeBlock, out diffParametersCount); obj_tech_debt += diffCodeBlock * (10/60); obj_tech_debt += diffcomplexityLevel * 1; obj_tech_debt += diffParametersCount * 1; obj_tech_debt += diffNestLevel * 1; } if (obj is Artech.Genexus.Common.Objects.Attribute && CheckKeyInINI(parsedData, SectionName, "AttributeBasedOnDomain", "true", "Attributes must be based on domains", filename)) { atts.Add(obj); //Attribute Has Domain Objects.AttributeHasDomain(objlist, output, ref recommendations, out cant); obj_tech_debt += cant * valor; } if (obj is SDT && CheckKeyInINI(parsedData, SectionName, "SDTBasedAttOrDomain", "true", "SDT items must be based on attributes or domains", filename)) { //SDTItems Has Domain Objects.SDTBasedOnAttDomain(objlist, output, ref recommendations, out cant); obj_tech_debt += cant * valor; } if (obj is Transaction && CheckKeyInINI(parsedData, SectionName, "AttributeBasedOnDomain", "true", "Attributes must be based on domains", filename)) { Objects.AttributeHasDomain(Objects.GetAttributesFromTrn((Transaction)obj), output, ref recommendations, out cant); obj_tech_debt += cant * valor; } if (recommendations != "") { Tuple<KBObject, string, double> recommend_tuple = new Tuple<KBObject, string, double>(obj, recommendations, obj_tech_debt); recommended_list.Add(recommend_tuple); } tech_debt_total += obj_tech_debt; } if (atts.Count > 0 && CheckKeyInINI(parsedData, SectionName, "AttributeWithoutTable", "true", "All attributes must be in table", filename)) { // Attributes without table Objects.AttributeWithoutTable(atts, output); } KBDoctorOutput.Message( "KBDoctor Review Object finished"); output.UnselectOutput(KBDOCTOR_OUTPUTID); output.SelectOutput("General"); lineswriter = new List<string[]>(); foreach (Tuple<KBObject, string, double> item in recommended_list) { string[] line = new string[] { Utility.linkObject(item.Item1), item.Item2, item.Item3.ToString() }; lineswriter.Add(line); } /* * Tiene todas las referencias? * Tiene calls que pueden ser UDP * Mas de un parametro de salida * Constantes en el código * Nombre "poco claro" / Descripcion "poco clara" * Si es modulo, revisar que no tenga objetos publicos no llamados * Si es modulo, revisar que no tenga objetos privados llamados desde fuera * Si es modulo, Valor de la propiedad ObjectVisibility <> Private * Atributo Varchar que debe ser char * Atributo Char que debe ser varchar * Column Title muy ancho para el ancho del atributo * Nombre del Control en pantalla por Default * Todos los eventos son invocados * */ }