public void MethodIsGenerated() { // arrange var method = new Method { FullName = "System.Boolean DD.Collections.BitSetArray::BitSetArray_<_SetItems>b__b_0(System.Int32)" }; // act var result = method.IsGenerated; // assert Assert.True (result); }
public void MethodIsNotGenerated() { // arrange var method = new Method { FullName = "System.Void DD.Collections.BitSetArray::_SetItems(System.Collections.Generic.IEnumerable`1<System.Int32>)" }; // act var result = method.IsGenerated; // assert Assert.False (result); }
public void MethodIsNotGeneratedFullNameIsNull() { // arrange var method = new Method { FullName = null }; // act var result = method.IsGenerated; // assert Assert.False (result); }
private string AsPropertyName(Method method) { if (!(method.IsGetter || method.IsSetter)) { return method.Name; } try { var methodName = method.Name; if (methodName.Contains("set_")) { var name = methodName.Split(new[] { "set_" }, System.StringSplitOptions.None)[1]; return name; } else if (methodName.Contains("get_")) { var type = methodName.Split(new[] { ' ' })[0]; var getWithEmptyParentheses = methodName.Split(new[] { "get_" }, System.StringSplitOptions.None)[1]; var firstParenthesis = getWithEmptyParentheses.IndexOf('('); var getWithoutEmptyParentheses = (firstParenthesis != -1) ? getWithEmptyParentheses.Substring(0, firstParenthesis) : getWithEmptyParentheses; var name = string.Format("{0}({1})", getWithoutEmptyParentheses, type); return name; } return methodName; } catch { return method.Name; } }
private static void TransformSequences_RemoveFalsePositiveUnvisited (Method method, CodeCoverageStringTextSource source, ICollection<Tuple<Method, SequencePoint>> toRemoveMethodSequencePoint) { // Select false unvisited right-curly-braces at generated "MoveNext" method // (Curly braces moved to generated "MoveNext" method and left unvisited) // Source is required here to identify curly braces if (method.CallName == "MoveNext" && source.FileFound && source.FileType == FileType.CSharp) { int countDown = 2; // remove up to two last right-curly-braces foreach (var sp in method.SequencePoints.Reverse()) { if (sp.FileId == method.FileRefUniqueId && sp.IsSingleCharSequencePoint && sp.VisitCount == 0) { // unvisited only if (countDown > 0) { if (source.GetText(sp) == "}") { toRemoveMethodSequencePoint.Add (new Tuple<Method, SequencePoint>(method, sp)); countDown -= 1; } } else { break; } } } } }
public void MethodCallNameWhenFullNameIsInvalid() { // arrange var method = new Method { FullName = "a::c" }; // act var result = method.CallName; // now covers all branches // assert Assert.True (result == ""); }
private static void CalculateCrapScore(Method method, Class @class) { method.CrapScore = Math.Round((decimal) Math.Pow(method.CyclomaticComplexity, 2) * (decimal) Math.Pow(1.0 - (double) (method.SequenceCoverage / (decimal) 100.0), 3.0) + method.CyclomaticComplexity, 2); // TODO: is 0 a possible crap score? method.Summary.MinCrapScore = Math.Max(0, method.CrapScore); method.Summary.MaxCrapScore = method.Summary.MinCrapScore; if (@class.Summary.MinCrapScore == 0) { @class.Summary.MinCrapScore = method.Summary.MinCrapScore; } @class.Summary.MinCrapScore = Math.Min(@class.Summary.MinCrapScore, method.CrapScore); @class.Summary.MaxCrapScore = Math.Max(@class.Summary.MaxCrapScore, method.CrapScore); }
public void MethodCallNameWhenFullNameIsEmpty() { // arrange var method = new Method { FullName = string.Empty }; // act var result = method.CallName; // assert Assert.True (result == ""); }
public Class() { Methods = new Method[0]; }
private Method BuildMethod(IEnumerable<Model.File> files, MethodDefinition methodDefinition) { var method = new Method { Name = methodDefinition.FullName, IsConstructor = methodDefinition.IsConstructor, IsStatic = methodDefinition.IsStatic, IsGetter = methodDefinition.IsGetter, IsSetter = methodDefinition.IsSetter, MetadataToken = methodDefinition.MetadataToken.ToInt32() }; if (methodDefinition.SafeGetMethodBody() == null) { if (methodDefinition.IsNative) method.MarkAsSkipped(SkippedMethod.NativeCode); else method.MarkAsSkipped(SkippedMethod.Unknown); return method; } if (_filter.ExcludeByAttribute(methodDefinition)) method.MarkAsSkipped(SkippedMethod.Attribute); var definition = methodDefinition; method.FileRef = files.Where(x => x.FullPath == ModulePath + "::" + methodDefinition.Module.Name) .Select(x => new FileRef { UniqueId = x.UniqueId }).FirstOrDefault(); return method; }
public void MethodCallNameWhenFullNameIsNull() { // arrange var method = new Method { FullName = null }; // act var result = method.CallName; // assert Assert.True (result == ""); }
public Class() { Methods = new Method[0]; Summary = new Summary(); }
private static Method BuildMethod(IEnumerable<File> files, IFilter filter, MethodDefinition methodDefinition, bool alreadySkippedDueToAttr, ICommandLine commandLine) { var method = new Method(); method.Name = methodDefinition.FullName; method.IsConstructor = methodDefinition.IsConstructor; method.IsStatic = methodDefinition.IsStatic; method.IsGetter = methodDefinition.IsGetter; method.IsSetter = methodDefinition.IsSetter; method.MetadataToken = methodDefinition.MetadataToken.ToInt32(); if (alreadySkippedDueToAttr || filter.ExcludeByAttribute(methodDefinition)) method.MarkAsSkipped(SkippedMethod.Attribute); else if (filter.ExcludeByFile(GetFirstFile(methodDefinition))) method.MarkAsSkipped(SkippedMethod.File); else if (commandLine.SkipAutoImplementedProperties && filter.IsAutoImplementedProperty(methodDefinition)) method.MarkAsSkipped(SkippedMethod.AutoImplementedProperty); var definition = methodDefinition; method.FileRef = files.Where(x => x.FullPath == GetFirstFile(definition)) .Select(x => new FileRef() {UniqueId = x.UniqueId}).FirstOrDefault(); return method; }
private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method method, CodeCoverageStringTextSource source, long startOffset, long finalOffset) { // foreach sequence point foreach (var sp in method.SequencePoints .Where (sp => sp.FileId == method.FileRefUniqueId && sp.BranchPoints.Count != 0)) { if (sp.Offset <= startOffset || sp.Offset >= finalOffset) { // doRemoveBranches where .Offset <= startOffset"{" or finalOffset"}" <= .Offset // this will exclude "{" and "}" compiler generated branches and majority of ccrewrite Code-Contract's sp.BranchPoints = new List<BranchPoint>(); } else { // branches not removed // check for other options by reading SequencePoint source var text = source.GetText(sp); // text is never null if (text.Length == 0) { ("Empty sequence-point at line: " + sp.StartLine + " column: " + sp.StartColumn).InformUser(); ("Source file: " + source.FilePath).InformUser(); return false; // signal error to caller's caller loop (break) } // Contract.Requires/Ensures is occasionally left inside method offset // Quick check for "C" before using Regex // Use Regex here! "Contract" and "." and "Requires/Ensures" // can be separated by spaces and newlines if (text[0] == 'C' && contractRegex.IsMatch(text)) { sp.BranchPoints = new List<BranchPoint>(); } // "in" keyword? if (text == "in") { // Remove generated ::MoveNext branches within "in" keyword // Not always removed in CecilSymbolManager (enumerated KeyValuePair) sp.BranchPoints = new List<BranchPoint>(); } } } return true; }
public void MethodIsNotGeneratedFullNameIsEmpty() { // arrange var method = new Method { FullName = string.Empty }; // act var result = method.IsGenerated; // assert Assert.False (result); }
private static void TransformSequences_RemoveCompilerGeneratedBranches(Method method, CodeCoverageStringTextSource source, ref long startOffset, ref long finalOffset) { // order SequencePoints by source order (Line/Column) var sourceLineOrderedSps = method.SequencePoints.OrderBy(sp => sp.StartLine).ThenBy(sp => sp.StartColumn).Where(sp => sp.FileId == method.FileRefUniqueId).ToArray(); // get "{" if on first two positions for (int index = 0; index < Math.Min (2, sourceLineOrderedSps.Length); index++) { if (source.GetText(sourceLineOrderedSps[0]) == "{") { startOffset = sourceLineOrderedSps[0].Offset; break; } } // get "}" if on last position if (source.GetText(sourceLineOrderedSps.Last()) == "}") { finalOffset = sourceLineOrderedSps.Last().Offset; } }
private static bool TransformSequences_RemoveCompilerGeneratedBranches (Method method, CodeCoverageStringTextSource source) { // Do we have C# source? if (source.FileType == FileType.CSharp) { if (source.FileFound) { // initialize offset with unreachable values long startOffset = long.MinValue; long finalOffset = long.MaxValue; if (!method.IsGenerated) { // fill offsets with values TransformSequences_RemoveCompilerGeneratedBranches(method, source, ref startOffset, ref finalOffset); } if (!TransformSequences_RemoveCompilerGeneratedBranches (method, source, startOffset, finalOffset)) { return false; // return error/failure to caller } } else { // Do as much possible without source // This will remove generated branches within "{", "}" and "in" (single-line SequencePoints) // but cannot remove Code Contract ccrewite generated branches foreach (var sp in method.SequencePoints) { if (sp.BranchPoints.Count != 0 && sp.StartLine == sp.EndLine && sp.EndColumn - sp.StartColumn <= 2) { // Zero, one or two character sequence point should not contain branches // Never found 0 character sequencePoint // Never found 1 character sequencePoint except "{" and "}" // Never found 2 character sequencePoint except "in" keyword // Afaik, c# cannot express branch condition in one or two characters of source code // Keyword "do" does not generate SequencePoint sp.BranchPoints = new List<BranchPoint>(); } } } } return true; }
private static void CalculateNPathComplexity(Method method) { method.NPathComplexity = 0; var nPaths = new Dictionary<int, int>(); if (method.BranchPoints.Any()) { foreach (var bp in method.BranchPoints.Where(b => b != null)) { if (nPaths.ContainsKey(bp.Offset)) { nPaths[bp.Offset] += 1; } else { nPaths.Add(bp.Offset, 1); } } } foreach (var branches in nPaths.Values) { if (method.NPathComplexity == 0) { method.NPathComplexity = branches; } else { method.NPathComplexity *= branches; } } }
private static void CalculateCyclomaticComplexity(Method method, Class @class) { method.Summary.MinCyclomaticComplexity = Math.Max(1, method.CyclomaticComplexity); method.Summary.MaxCyclomaticComplexity = method.Summary.MinCyclomaticComplexity; if (@class.Summary.MinCyclomaticComplexity == 0) @class.Summary.MinCyclomaticComplexity = method.Summary.MinCyclomaticComplexity; @class.Summary.MinCyclomaticComplexity = Math.Min(@class.Summary.MinCyclomaticComplexity, method.CyclomaticComplexity); @class.Summary.MaxCyclomaticComplexity = Math.Max(@class.Summary.MaxCyclomaticComplexity, method.CyclomaticComplexity); }
private static void ProcessMethodData(Method method, Class @class) { if (method.MethodPoint != null) { method.Visited = (method.MethodPoint.VisitCount > 0); } method.Summary.NumBranchPoints = method.BranchPoints.Length; method.Summary.VisitedBranchPoints = method.BranchPoints.Count(pt => pt.VisitCount != 0); method.Summary.NumSequencePoints = method.SequencePoints.Length; method.Summary.VisitedSequencePoints = method.SequencePoints.Count(pt => pt.VisitCount != 0); if (method.Summary.NumSequencePoints > 0) method.Summary.NumBranchPoints += 1; if (method.Summary.VisitedSequencePoints > 0) method.Summary.VisitedBranchPoints += 1; if (method.FileRef != null) { method.Summary.NumMethods = 1; method.Summary.VisitedMethods = (method.Visited) ? 1 : 0; } AddPoints(@class.Summary, method.Summary); CalculateCoverage(method.Summary); method.SequenceCoverage = method.Summary.SequenceCoverage; method.BranchCoverage = method.Summary.BranchCoverage; CalculateNPathComplexity(method); CalculateCyclomaticComplexity(method, @class); }
public PropertyMethodNode(Method method) : base(method) { }
public MethodNode(Method method) { Method = method; }
private static void GetMethodsForType(IEnumerable<TypeDefinition> typeDefinitions, Class type, List<Method> methods, File[] files) { foreach (var typeDefinition in typeDefinitions) { if (typeDefinition.FullName == type.FullName) { foreach (var methodDefinition in typeDefinition.Methods) { if (!methodDefinition.IsConstructor) { var method = new Method() { Name = methodDefinition.FullName, MetadataToken = methodDefinition.MetadataToken.ToInt32() }; var definition = methodDefinition; method.FileRef = files.Where(x => x.FullPath == GetFirstFile(definition)).Select(x => new FileRef() {UniqueId = x.UniqueId}).FirstOrDefault(); methods.Add(method); } } } if (typeDefinition.HasNestedTypes) GetMethodsForType(typeDefinition.NestedTypes, type, methods, files); } }
public void MethodCallnameStandard() { // arrange var method = new Method { FullName = "System.Void DD.Collections.BitSetArray::_SetItems(System.Collections.Generic.IEnumerable`1<System.Int32>)" }; // act var result = method.CallName; // assert Assert.True (result == "_SetItems"); }
private static Method BuildMethod(IEnumerable<File> files, IFilter filter, MethodDefinition methodDefinition, bool alreadySkippedDueToAttr) { var method = new Method(); method.Name = methodDefinition.FullName; method.IsConstructor = methodDefinition.IsConstructor; method.IsStatic = methodDefinition.IsStatic; method.IsGetter = methodDefinition.IsGetter; method.IsSetter = methodDefinition.IsSetter; method.MetadataToken = methodDefinition.MetadataToken.ToInt32(); if (alreadySkippedDueToAttr || filter.ExcludeByAttribute(methodDefinition)) method.SkippedDueTo = SkippedMethod.Attribute; else if (filter.ExcludeByFile(GetFirstFile(methodDefinition))) method.SkippedDueTo = SkippedMethod.File; var definition = methodDefinition; method.FileRef = files.Where(x => x.FullPath == GetFirstFile(definition)) .Select(x => new FileRef() {UniqueId = x.UniqueId}).FirstOrDefault(); return method; }
public void MethodCallNameTwice() { // arrange var method = new Method { FullName = "System.Boolean DD.Collections.BitSetArray::BitSetArray_<_SetItems>b__b_0(System.Int32)" }; // act twice to cover cached result var result = method.CallName; result = method.CallName; // assert Assert.True (result == "BitSetArray_<_SetItems>b__b_0"); }