diff --git a/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs b/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs
index b6e2f8570b..9ffca969be 100644
--- a/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs
+++ b/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs
@@ -204,6 +204,8 @@ namespace ICSharpCode.CodeQualityAnalysis
} else if (content == "Method") {
cbxMetrics.Items.Add(new ComboBoxItem { Content = "IL instructions" });
+ cbxMetrics.Items.Add(new ComboBoxItem { Content = "Cyclomatic Complexity" });
+ cbxMetrics.Items.Add(new ComboBoxItem { Content = "Variables" });
}
}
@@ -219,6 +221,8 @@ namespace ICSharpCode.CodeQualityAnalysis
var metric = metricItem.Content.ToString();
+ // TODO: Redone this with enums or some smarter way
+
if (level == "Assembly") {
//cbxMetrics.Items.Add(new ComboBoxItem { Content = });
} else if (level == "Namespace") {
@@ -228,12 +232,19 @@ namespace ICSharpCode.CodeQualityAnalysis
} else if (level == "Field") {
} else if (level == "Method") {
- if (metric == "IL instructions") {
- treemap.ItemsSource = from ns in MetricsReader.MainModule.Namespaces
- from type in ns.Types
- from method in type.Methods
- select method;
- }
+ treemap.ItemsSource = from ns in MetricsReader.MainModule.Namespaces
+ from type in ns.Types
+ from method in type.Methods
+ select method;
+
+ if (metric == "IL instructions")
+ treemap.ItemDefinition.ValuePath = "Instructions.Count";
+
+ if (metric == "Cyclomatic Complexity")
+ treemap.ItemDefinition.ValuePath = "CyclomaticComplexity";
+
+ if (metric == "Variables")
+ treemap.ItemDefinition.ValuePath = "Variables";
}
}
}
diff --git a/src/AddIns/Analysis/CodeQuality/Src/Method.cs b/src/AddIns/Analysis/CodeQuality/Src/Method.cs
index f4720a7b77..cafbd2a289 100644
--- a/src/AddIns/Analysis/CodeQuality/Src/Method.cs
+++ b/src/AddIns/Analysis/CodeQuality/Src/Method.cs
@@ -111,6 +111,16 @@ namespace ICSharpCode.CodeQualityAnalysis
///
public bool IsReturnTypeGenericInstance { get; set; }
+ ///
+ /// Cyclomatic Complexity of the method
+ ///
+ public int CyclomaticComplexity { get; set; }
+
+ ///
+ /// The number of variables declared in the body of the method
+ ///
+ public int Variables { get; set; }
+
public Method()
{
Parameters = new HashSet();
@@ -127,6 +137,9 @@ namespace ICSharpCode.CodeQualityAnalysis
IsReturnTypeGenericInstance = false;
Dependency = null;
+
+ CyclomaticComplexity = 0;
+ Variables = 0;
}
public Relationship GetRelationship(INode node)
@@ -149,6 +162,8 @@ namespace ICSharpCode.CodeQualityAnalysis
builder.Append(Environment.NewLine);
builder.AppendLine(String.Format("Name: {0}", Name));
builder.AppendLine(String.Format("Parameters: {0}", Parameters.Count));
+ builder.AppendLine(String.Format("Cyclomatic Complexity: {0}", CyclomaticComplexity));
+ builder.AppendLine(String.Format("Variables: {0}", Variables));
// more to come
builder.Append(Environment.NewLine);
diff --git a/src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs b/src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs
index 95ab741e0c..ca712384bc 100644
--- a/src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs
+++ b/src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs
@@ -131,19 +131,19 @@ namespace ICSharpCode.CodeQualityAnalysis
IsStruct = typeDefinition.IsValueType && !typeDefinition.IsEnum && typeDefinition.IsSealed,
IsInternal = typeDefinition.IsNotPublic,
IsDelegate = (typeDefinition.BaseType != null ?
- typeDefinition.BaseType.FullName == "System.MulticastDelegate" : false),
+ typeDefinition.BaseType.FullName == "System.MulticastDelegate" : false),
IsNestedPrivate = typeDefinition.IsNestedPrivate,
IsNestedPublic = typeDefinition.IsNestedPublic,
IsNestedProtected = (!typeDefinition.IsNestedPrivate && !typeDefinition.IsNestedPublic &&
- typeDefinition.IsNestedFamily)
+ typeDefinition.IsNestedFamily)
};
// try find namespace
var nsName = GetNamespaceName(typeDefinition);
var ns = (from n in module.Namespaces
- where n.Name == nsName
- select n).SingleOrDefault();
+ where n.Name == nsName
+ select n).SingleOrDefault();
if (ns == null)
{
@@ -182,9 +182,9 @@ namespace ICSharpCode.CodeQualityAnalysis
if (typeDefinition.BaseType != null)
{
var baseType = (from n in module.Namespaces
- from t in n.Types
- where (t.FullName == FormatTypeName(typeDefinition.BaseType, true))
- select t).SingleOrDefault();
+ from t in n.Types
+ where (t.FullName == FormatTypeName(typeDefinition.BaseType, true))
+ select t).SingleOrDefault();
type.BaseType = baseType; // if baseType is null so propably inherits from another assembly
@@ -192,7 +192,7 @@ namespace ICSharpCode.CodeQualityAnalysis
{
type.IsBaseTypeGenericInstance = true;
type.GenericBaseTypes.UnionWith(ReadGenericArguments(type.Namespace.Module,
- (GenericInstanceType)typeDefinition.BaseType));
+ (GenericInstanceType)typeDefinition.BaseType));
}
}
@@ -202,9 +202,9 @@ namespace ICSharpCode.CodeQualityAnalysis
foreach (var ic in typeDefinition.Interfaces)
{
var implementedIc = (from n in module.Namespaces
- from t in n.Types
- where (t.FullName == FormatTypeName(ic, true))
- select t).SingleOrDefault();
+ from t in n.Types
+ where (t.FullName == FormatTypeName(ic, true))
+ select t).SingleOrDefault();
if (implementedIc != null)
type.ImplementedInterfaces.Add(implementedIc);
@@ -212,7 +212,7 @@ namespace ICSharpCode.CodeQualityAnalysis
if (ic.IsGenericInstance)
{
type.GenericBaseTypes.UnionWith(ReadGenericArguments(type.Namespace.Module,
- (GenericInstanceType)ic));
+ (GenericInstanceType)ic));
}
}
}
@@ -307,7 +307,7 @@ namespace ICSharpCode.CodeQualityAnalysis
{
field.IsGenericInstance = true;
field.GenericTypes.UnionWith(ReadGenericArguments(type.Namespace.Module,
- (GenericInstanceType)fieldDefinition.FieldType));
+ (GenericInstanceType)fieldDefinition.FieldType));
}
field.FieldType = fieldType;
@@ -336,7 +336,8 @@ namespace ICSharpCode.CodeQualityAnalysis
IsAbstract = methodDefinition.IsAbstract,
IsSetter = methodDefinition.IsSetter,
IsGetter = methodDefinition.IsGetter,
- IsVirtual = methodDefinition.IsVirtual
+ IsVirtual = methodDefinition.IsVirtual,
+ Variables = methodDefinition.Body != null ? methodDefinition.Body.Variables.Count : 0
};
var returnType =
@@ -351,7 +352,7 @@ namespace ICSharpCode.CodeQualityAnalysis
{
method.IsReturnTypeGenericInstance = true;
method.GenericReturnTypes.UnionWith(ReadGenericArguments(type.Namespace.Module,
- (GenericInstanceType) methodDefinition.ReturnType));
+ (GenericInstanceType) methodDefinition.ReturnType));
}
// reading types from parameters
@@ -378,7 +379,7 @@ namespace ICSharpCode.CodeQualityAnalysis
{
param.IsGenericInstance = true;
param.GenericTypes = ReadGenericArguments(type.Namespace.Module,
- (GenericInstanceType) parameter.ParameterType);
+ (GenericInstanceType) parameter.ParameterType);
}
method.Parameters.Add(param);
@@ -391,8 +392,8 @@ namespace ICSharpCode.CodeQualityAnalysis
foreach (MethodDefinition methodDefinition in methods)
{
var method = (from m in type.Methods
- where m.Name == FormatMethodName(methodDefinition)
- select m).SingleOrDefault();
+ where m.Name == FormatMethodName(methodDefinition)
+ select m).SingleOrDefault();
if (methodDefinition.Body != null)
{
@@ -408,15 +409,19 @@ namespace ICSharpCode.CodeQualityAnalysis
/// A method definition with instructions
/// A collection of instructions
public void ReadInstructions(Method method, MethodDefinition methodDefinition,
- Collection instructions)
+ Collection instructions)
{
foreach (var instruction in instructions)
{
method.Instructions.Add(new Instruction
- {
- DeclaringMethod = method,
- // Operand = instruction.Operand.ToString() // for now operand as string should be enough
- });
+ {
+ DeclaringMethod = method,
+ // Operand = instruction.Operand.ToString() // for now operand as string should be enough
+ });
+
+ // IL cyclomatic complexity
+ if (instruction.OpCode.FlowControl == FlowControl.Cond_Branch)
+ method.CyclomaticComplexity++;
var operand = ReadOperand(instruction);
@@ -424,15 +429,15 @@ namespace ICSharpCode.CodeQualityAnalysis
{
var md = operand as MethodDefinition;
var type = (from n in method.DeclaringType.Namespace.Module.Namespaces
- from t in n.Types
- where t.FullName == FormatTypeName(md.DeclaringType, true)
- select t).SingleOrDefault();
+ from t in n.Types
+ where t.FullName == FormatTypeName(md.DeclaringType, true)
+ select t).SingleOrDefault();
method.TypeUses.Add(type);
var findTargetMethod = (from m in type.Methods
- where m.Name == FormatMethodName(md)
- select m).SingleOrDefault();
+ where m.Name == FormatMethodName(md)
+ select m).SingleOrDefault();
if (findTargetMethod != null && type == method.DeclaringType)
method.MethodUses.Add(findTargetMethod);
@@ -442,8 +447,8 @@ namespace ICSharpCode.CodeQualityAnalysis
{
var fd = operand as FieldDefinition;
var field = (from f in method.DeclaringType.Fields
- where f.Name == fd.Name
- select f).SingleOrDefault();
+ where f.Name == fd.Name
+ select f).SingleOrDefault();
if (field != null)
method.FieldUses.Add(field);