private List <Issue> ApplyRule(CaDETClass c) { List <Issue> issues = _rules.Select(r => r.Validate(c.FullName, c.Metrics)).ToList(); issues.AddRange(_dynamicRules.Select(r => r.Validate(c.FullName, c.Metrics)).ToList()); return(issues); }
private int CountOwnFieldAndAccessorAccessed(CaDETClass parsedClass, CaDETMember method) { int counter = method.AccessedFields.Count(field => Enumerable.Contains(parsedClass.Fields, field)); counter += method.AccessedAccessors.Count(accessor => Enumerable.Contains(parsedClass.Members, accessor)); return(counter); }
private CaDETClass LinkParent(List <CaDETClass> classes, CaDETClass parent) { if (parent.Name.Equals("object")) { return(null); } return(classes.FirstOrDefault(c => c.FullName.Equals(parent.Name))); }
// Implementation based on https://github.com/mauricioaniche/ck private double CountMaxNestedBlocks(CaDETClass parsedClass) { if (!parsedClass.Members.Any()) { return(0); } return(parsedClass.Members.Max(method => method.Metrics[CaDETMetric.MMNB])); }
private List <string> GetClassNames(CaDETClass caDETClass) { var names = new List <string> { caDETClass.Name }; names.AddRange(caDETClass.Fields.Select(f => f.Name)); return(names); }
private int CountUniqueMethodInvocations(CaDETClass parsedClass) { var invokedMethods = new HashSet <CaDETMember>(); foreach (var member in parsedClass.Members) { invokedMethods.UnionWith(member.InvokedMethods.ToList()); } return(invokedMethods.Count()); }
internal CaDETMember CreateBasicMember(CaDETClass parent) { _member.Modifiers = _cSharpMember.Modifiers.Select(modifier => new CaDETModifier(modifier.ValueText)).ToList(); _member.SourceCode = _cSharpMember.ToString(); _member.Parent = parent; _member.Params = GetMethodParams(); _member.ReturnType = GetMethodReturnType(); _member.Variables = GetMethodVariables(); return(_member); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountDependencies(CaDETClass parsedClass) { List <CaDETClass> allDependencies = new List <CaDETClass>(); allDependencies.AddRange(parsedClass.GetFieldLinkedTypes().Distinct()); allDependencies.AddRange(parsedClass.GetMethodLinkedReturnTypes().Distinct()); allDependencies.AddRange(parsedClass.GetMethodLinkedVariableTypes().Distinct()); var uniqueDependencies = allDependencies.GroupBy(d => d.FullName).Select(d => d.First()); return(uniqueDependencies.Count()); }
/// <summary> /// ATFD: Access To Foreign Data /// DOI: 10.1109/ESEM.2009.5314231 /// </summary> private int GetAccessToForeignData(CaDETClass parsedClass) { ISet <CaDETField> accessedExternalFields = new HashSet <CaDETField>(); ISet <CaDETMember> accessedExternalAccessors = new HashSet <CaDETMember>(); foreach (var member in parsedClass.Members) { accessedExternalFields.UnionWith(member.AccessedFields.Where(f => !f.Parent.Equals(member.Parent))); accessedExternalAccessors.UnionWith(member.AccessedAccessors.Where(a => !a.Parent.Equals(member.Parent))); } return(accessedExternalAccessors.Count + accessedExternalFields.Count); }
/// <summary> /// TCC - Tight Class Cohesion /// DOI: 10.1145/223427.211856 /// </summary> private double GetTightClassCohesion(CaDETClass parsedClass) { int N = GetNumberOfMethodsDeclared(parsedClass); double NP = (N * (N - 1)) / 2; if (NP == 0) { return(-1); } return(Math.Round(CountMethodPairsThatShareAccessToAFieldOrAccessor(parsedClass.Members) / NP, 2)); }
public void Build_code_model_from_repository() { CodeModelFactory factory = new CodeModelFactory(); var project = factory.CreateProject("C:/repo"); project.Classes.ShouldNotBeEmpty(); CaDETClass conflict = project.Classes.Find(c => c.FullName.Equals("LibGit2Sharp.Conflict")); conflict.ShouldNotBeNull(); conflict.Fields.ShouldContain(f => f.Name.Equals("ancestor")); conflict.Fields.ShouldContain(f => f.Name.Equals("ours")); conflict.Fields.ShouldContain(f => f.Name.Equals("theirs")); conflict.Members.ShouldContain(m => m.Name.Equals("Conflict") && m.Type.Equals(CaDETMemberType.Constructor) && m.AccessedFields.Count == 3); conflict.Members.ShouldContain(m => m.Name.Equals("Equals") && m.Type.Equals(CaDETMemberType.Method) && m.AccessedFields.Count == 1); conflict.Metrics[CaDETMetric.CLOC].ShouldBe(108); conflict.Metrics[CaDETMetric.LCOM].ShouldBe(0.833); conflict.Metrics[CaDETMetric.NAD].ShouldBe(4); conflict.Metrics[CaDETMetric.NMD].ShouldBe(3); conflict.Metrics[CaDETMetric.WMC].ShouldBe(8); CaDETClass certificate = project.Classes.Find(c => c.FullName.Equals("LibGit2Sharp.Certificate")); certificate.ShouldNotBeNull(); certificate.Members.ShouldBeEmpty(); certificate.Fields.ShouldBeEmpty(); certificate.Metrics[CaDETMetric.LCOM].ShouldBe(-1); certificate.Metrics[CaDETMetric.CLOC].ShouldBe(3); certificate.Metrics[CaDETMetric.NAD].ShouldBe(0); certificate.Metrics[CaDETMetric.NMD].ShouldBe(0); certificate.Metrics[CaDETMetric.WMC].ShouldBe(0); CaDETClass handles = project.Classes.Find(c => c.FullName.Equals("LibGit2Sharp.Core.Handles.Libgit2Object")); handles.ShouldNotBeNull(); handles.Fields.ShouldContain(f => f.Name.Equals("ptr")); handles.Members.ShouldContain(m => m.Name.Equals("Handle") && m.Type.Equals(CaDETMemberType.Property)); handles.Members.ShouldContain(m => m.Name.Equals("Dispose") && m.Type.Equals(CaDETMemberType.Method) && m.InvokedMethods.Count == 1 && m.AccessedFields.Count == 0 && m.AccessedAccessors.Count == 0); handles.Metrics[CaDETMetric.LCOM].ShouldBe(0.667); handles.Metrics[CaDETMetric.CLOC].ShouldBe(100); handles.Metrics[CaDETMetric.NAD].ShouldBe(3); handles.Metrics[CaDETMetric.NMD].ShouldBe(4); handles.Metrics[CaDETMetric.WMC].ShouldBe(10); }
private bool FileContainsOuterMostClass(CaDETClass projectClass, string fileText) { var c = projectClass; while (c.IsInnerClass) { c = c.OuterClass; } if (c.ContainerName.Equals("")) { return(fileText.Contains(c.SourceCode)); //When namespace is not defined (global). } var namespaceName = GetLanguagePackageName() + " " + c.ContainerName; return(fileText.Contains(c.SourceCode) && fileText.Contains(namespaceName) && !fileText.Contains(namespaceName + ".")); //To avoid subpackages. }
private CaDETClass ParseClass(SemanticModel semanticModel, ClassDeclarationSyntax node) { var symbol = semanticModel.GetDeclaredSymbol(node); var parsedClass = new CaDETClass { Name = symbol.Name, FullName = symbol.ToDisplayString(), SourceCode = node.ToString() }; parsedClass.Modifiers = GetModifiers(node); parsedClass.Parent = new CaDETClass { Name = symbol.BaseType.ToString() }; parsedClass.Fields = ParseFields(node.Members, parsedClass, semanticModel); parsedClass.Members = ParseMethods(node.Members, parsedClass, semanticModel); return(parsedClass); }
private double GetLackOfCohesionOfMethods(CaDETClass parsedClass) { //TODO: Will need to reexamine the way we look at accessors and fields double maxCohesion = (GetNumberOfAttributesDefined(parsedClass)) * GetNumberOfMethodsDeclared(parsedClass); if (maxCohesion == 0) { return(-1); } double methodFieldAccess = 0; foreach (var method in parsedClass.Members.Where(method => method.Type.Equals(CaDETMemberType.Method))) { methodFieldAccess += CountOwnFieldAndAccessorAccessed(parsedClass, method); } return(Math.Round(1 - methodFieldAccess / maxCohesion, 3)); }
public Dictionary <CaDETMetric, double> GetMetricsForCodeSnippet(string snippetId) { CaDETClass classInstance = Classes.FirstOrDefault(c => c.FullName.Equals(snippetId)); if (classInstance != null) { return(classInstance.Metrics); } CaDETMember memberInstance = null; foreach (var cl in Classes) { memberInstance = cl.Members.FirstOrDefault(m => m.ToString().Equals(snippetId)); if (memberInstance != null) { break; } } return(memberInstance.Metrics); }
private void CreateClassMemberBuilders(CaDETClass parent, IEnumerable <MemberDeclarationSyntax> members, SemanticModel semanticModel) { var classMemberBuilders = new List <CSharpCaDETMemberBuilder>(); foreach (var member in members) { try { ValidateNoPartialModifier(member); classMemberBuilders.Add(new CSharpCaDETMemberBuilder(member, semanticModel)); } catch (InappropriateMemberTypeException) { //MemberDeclarationSyntax is not property, constructor, or method. } catch (PartialIsNotSupportedException) { //Skips members with partial keyword. } } _memberBuilders.Add(parent, classMemberBuilders); }
//TODO: See how this class will change with new metrics and try to decouple it from CSharp (e.g., by moving to CaDETClassMetric constructor) //TODO: Currently we see feature envy for CaDETClass. internal Dictionary <CaDETMetric, double> CalculateClassMetrics(CaDETClass parsedClass) { return(new Dictionary <CaDETMetric, double> { [CaDETMetric.CLOC] = GetLinesOfCode(parsedClass.SourceCode), [CaDETMetric.NMD] = GetNumberOfMethodsDeclared(parsedClass), [CaDETMetric.NAD] = GetNumberOfAttributesDefined(parsedClass), [CaDETMetric.NMD_NAD] = GetNumberOfMethodsDeclared(parsedClass) + GetNumberOfAttributesDefined(parsedClass), [CaDETMetric.WMC] = GetWeightedMethodPerClass(parsedClass), [CaDETMetric.LCOM] = GetLackOfCohesionOfMethods(parsedClass), [CaDETMetric.TCC] = GetTightClassCohesion(parsedClass), [CaDETMetric.ATFD] = GetAccessToForeignData(parsedClass), [CaDETMetric.CNOR] = CountReturnStatements(parsedClass), [CaDETMetric.CNOL] = CountLoops(parsedClass), [CaDETMetric.CNOC] = CountComparisonOperators(parsedClass), [CaDETMetric.CNOA] = CountNumberOfAssignments(parsedClass), [CaDETMetric.NOPM] = CountNumberOfPrivateMethods(parsedClass), [CaDETMetric.NOPF] = CountNumberOfProtectedFields(parsedClass), [CaDETMetric.CMNB] = CountMaxNestedBlocks(parsedClass), [CaDETMetric.RFC] = CountUniqueMethodInvocations(parsedClass), [CaDETMetric.CBO] = CountDependencies(parsedClass), }); }
// Implementation based on https://github.com/mauricioaniche/ck private double CountLoops(CaDETClass parsedClass) { return(parsedClass.Members.Sum(method => method.Metrics[CaDETMetric.MNOL])); }
// Implementation based on https://github.com/mauricioaniche/ck private double CountNumberOfAssignments(CaDETClass parsedClass) { return(parsedClass.Members.Sum(method => method.Metrics[CaDETMetric.MNOA])); }
private int GetNumberOfMethodsDeclared(CaDETClass parsedClass) { return(parsedClass.Members.Count(method => method.Type.Equals(CaDETMemberType.Method))); }
private List <CaDETMember> ParseMethods(IEnumerable <MemberDeclarationSyntax> members, CaDETClass parent, SemanticModel semanticModel) { CreateClassMemberBuilders(parent, members, semanticModel); return(_memberBuilders[parent].Select(builder => builder.CreateBasicMember(parent)).Where(method => method != null).ToList()); }
private List <CaDETField> ParseFields(IEnumerable <MemberDeclarationSyntax> nodeMembers, CaDETClass parent, SemanticModel model) { List <CaDETField> fields = new List <CaDETField>(); foreach (var node in nodeMembers) { if (!(node is FieldDeclarationSyntax fieldDeclaration)) { continue; } fields.AddRange(fieldDeclaration.Declaration.Variables.Select( field => new CaDETField { Name = field.Identifier.Text, Parent = parent, Modifiers = GetModifiers(node), Type = new CaDETLinkedType() { FullType = ((IFieldSymbol)model.GetDeclaredSymbol(field)).Type.ToString() } })); } return(fields); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountNumberOfPrivateMethods(CaDETClass parsedClass) { return(parsedClass.Members.Count(method => method.Type.Equals(CaDETMemberType.Method) && method.Modifiers.Any(m => m.Value == CaDETModifierValue.Private))); }
// Implementation based on https://github.com/mauricioaniche/ck private double CountComparisonOperators(CaDETClass parsedClass) { return(parsedClass.Members.Sum(method => method.Metrics[CaDETMetric.MNOC])); }
private int GetNumberOfAttributesDefined(CaDETClass parsedClass) { //TODO: Probably should expand to include simple accessors that do not have a related field. //TODO: It is C# specific, but this is the CSSharpMetricCalculator return(parsedClass.Fields.Count + parsedClass.Members.Count(m => m.IsFieldDefiningAccessor())); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountNumberOfProtectedFields(CaDETClass parsedClass) { return(parsedClass.Fields.Count(field => field.Modifiers.Any(f => f.Value == CaDETModifierValue.Protected))); }
// Implementation based on https://github.com/mauricioaniche/ck private double CountReturnStatements(CaDETClass parsedClass) { return(parsedClass.Members.Sum(method => method.Metrics[CaDETMetric.MNOR])); }
private Issue ApplyRule(CaDETClass c) { return(_rule.Validate(c.FullName, c.Metrics)); }
/// <summary> /// WMC - Weighted Method Per Class /// DOI: 10.1109/32.295895 /// </summary> private double GetWeightedMethodPerClass(CaDETClass parsedClass) { return(parsedClass.Members.Sum(method => method.Metrics[CaDETMetric.CYCLO])); }