Skip to content

Commit

Permalink
Use Gendarme rules to calculate Cyclomatic Complexity
Browse files Browse the repository at this point in the history
  • Loading branch information
sawilde committed Jul 11, 2011
1 parent 1a26329 commit 4309313
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 27 deletions.
Expand Up @@ -49,6 +49,7 @@ private void BuildClassModel(Class @class, File[] files)
foreach (var method in methods)
{
method.SequencePoints = _symbolManager.GetSequencePointsForToken(method.MetadataToken);
method.CyclomaticComplexity = _symbolManager.GetCyclomaticComplexityForToken(method.MetadataToken);
}

@class.Methods = methods.Where(method => method.SequencePoints != null).ToArray();
Expand Down
4 changes: 4 additions & 0 deletions main/OpenCover.Framework/Model/Method.cs
Expand Up @@ -4,6 +4,7 @@
// This source code is released under the MIT License; see the accompanying license file.
//
using System.Collections.Generic;
using System.Xml.Serialization;

namespace OpenCover.Framework.Model
{
Expand All @@ -16,5 +17,8 @@ public class Method
public string Name { get; set; }
public FileRef FileRef { get; set; }
public SequencePoint[] SequencePoints { get; set; }

[XmlAttribute("cyclomaticComplexity")]
public int CyclomaticComplexity { get; set; }
}
}
7 changes: 6 additions & 1 deletion main/OpenCover.Framework/OpenCover.Framework.csproj
Expand Up @@ -40,7 +40,12 @@
<AssemblyOriginatorKeyFile>..\..\build\Version\opencover.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="ISymWrapper" />
<Reference Include="Gendarme.Framework">
<HintPath>..\..\tools\Gendarme.2.11\Signed\Gendarme.Framework.dll</HintPath>
</Reference>
<Reference Include="Gendarme.Rules.Maintainability">
<HintPath>..\..\tools\Gendarme.2.11\Signed\Gendarme.Rules.Maintainability.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity, Version=2.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\tools\EnterpriseLibrary\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
Expand Down
69 changes: 43 additions & 26 deletions main/OpenCover.Framework/Symbols/CecilSymbolManager.cs
Expand Up @@ -208,44 +208,61 @@ public SequencePoint[] GetSequencePointsForToken(int token)
return list.ToArray();
}

public int GetCyclomaticComplexityForToken(int token)
{
IEnumerable<TypeDefinition> typeDefinitions = SourceAssembly.MainModule.Types;
return GetCyclomaticComplexityForToken(typeDefinitions, token);
}

private static void GetSequencePointsForToken(IEnumerable<TypeDefinition> typeDefinitions, int token, List<SequencePoint> list)
{
foreach (var typeDefinition in typeDefinitions)
{
foreach (var methodDefinition in typeDefinition.Methods)
foreach (var methodDefinition in
typeDefinition.Methods
.Where(methodDefinition => methodDefinition.MetadataToken.ToInt32() == token)
.Where(methodDefinition => methodDefinition.Body != null && methodDefinition.Body.Instructions != null))
{
if (methodDefinition.MetadataToken.ToInt32() == token)
UInt32 ordinal = 0;
foreach (var instruction in methodDefinition.Body.Instructions)
{
if (methodDefinition.Body != null && methodDefinition.Body.Instructions != null)
if (instruction.SequencePoint != null &&
instruction.SequencePoint.StartLine != stepOverLineCode)
{
//if (methodDefinition.Body.Instructions.Any(x => x.SequencePoint == null))
{
UInt32 ordinal = 0;
foreach (var instruction in methodDefinition.Body.Instructions)
{
if (instruction.SequencePoint != null &&
instruction.SequencePoint.StartLine != stepOverLineCode)
{
var sp = instruction.SequencePoint;
var point = new SequencePoint()
{
EndColumn = sp.EndColumn,
EndLine = sp.EndLine,
Offset = instruction.Offset,
Ordinal = ordinal++,
StartColumn = sp.StartColumn,
StartLine = sp.StartLine,
};
list.Add(point);
}
}
}

var sp = instruction.SequencePoint;
var point = new SequencePoint()
{
EndColumn = sp.EndColumn,
EndLine = sp.EndLine,
Offset = instruction.Offset,
Ordinal = ordinal++,
StartColumn = sp.StartColumn,
StartLine = sp.StartLine,
};
list.Add(point);
}
}
}
if (typeDefinition.HasNestedTypes) GetSequencePointsForToken(typeDefinition.NestedTypes, token, list);
}
}

private static int GetCyclomaticComplexityForToken(IEnumerable<TypeDefinition> typeDefinitions, int token)
{
var ret = 0;
foreach (var typeDefinition in typeDefinitions)
{
foreach (var methodDefinition in
typeDefinition.Methods
.Where(methodDefinition => methodDefinition.MetadataToken.ToInt32() == token)
.Where(methodDefinition => methodDefinition.Body != null && methodDefinition.Body.Instructions != null))
{
return Gendarme.Rules.Maintainability.AvoidComplexMethodsRule.GetCyclomaticComplexity(methodDefinition);
}
if (typeDefinition.HasNestedTypes) ret = GetCyclomaticComplexityForToken(typeDefinition.NestedTypes, token);
if (ret != 0) return ret;
}
return 0;
}
}
}
2 changes: 2 additions & 0 deletions main/OpenCover.Framework/Symbols/ISymbolManager.cs
Expand Up @@ -24,6 +24,8 @@ public interface ISymbolManager

SequencePoint[] GetSequencePointsForToken(int token);

int GetCyclomaticComplexityForToken(int token);

AssemblyDefinition SourceAssembly { get; }
}
}
2 changes: 2 additions & 0 deletions main/OpenCover.Installer/Product.wxs
Expand Up @@ -26,6 +26,8 @@
<File Id="MICROSOFT_PRACTICES_UNITY_DLL" Source="..\bin\Release\Microsoft.Practices.Unity.dll" />
<File Id="MONO_CECIL_DLL" Source="..\bin\Release\Mono.Cecil.dll" />
<File Id="MONO_CECIL_PDB_DLL" Source="..\bin\Release\Mono.Cecil.Pdb.dll" />
<File Id="GENDARME_FRAMEWORK_DLL" Source="..\bin\Release\Gendarme.Framework.dll" />
<File Id="GENDARME_RULES_MAINTAINABILITY_DLL" Source="..\bin\Release\Gendarme.Rules.Maintainability.dll" />
<File Id="SAMPLE_CMD" Source="Assets\Sample.cmd" Name="Sample.cmd" />
<File Id="SAMPLE64_CMD" Source="Assets\Sample64.cmd" Name="Sample64.cmd" />
<File Id="LICENCE_TXT" Source="..\..\License.md" Name="License.txt" />
Expand Down

0 comments on commit 4309313

Please sign in to comment.