Browse Source

Added support for Cyclomatic Complexity metric and for the number of variables inside of a method.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6435 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Tomáš Linhart 15 years ago
parent
commit
b7dd8b62f3
  1. 23
      src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs
  2. 15
      src/AddIns/Analysis/CodeQuality/Src/Method.cs
  3. 65
      src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs

23
src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs

@ -204,6 +204,8 @@ namespace ICSharpCode.CodeQualityAnalysis @@ -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 @@ -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 @@ -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";
}
}
}

15
src/AddIns/Analysis/CodeQuality/Src/Method.cs

@ -111,6 +111,16 @@ namespace ICSharpCode.CodeQualityAnalysis @@ -111,6 +111,16 @@ namespace ICSharpCode.CodeQualityAnalysis
/// </summary>
public bool IsReturnTypeGenericInstance { get; set; }
/// <summary>
/// Cyclomatic Complexity of the method
/// </summary>
public int CyclomaticComplexity { get; set; }
/// <summary>
/// The number of variables declared in the body of the method
/// </summary>
public int Variables { get; set; }
public Method()
{
Parameters = new HashSet<MethodParameter>();
@ -127,6 +137,9 @@ namespace ICSharpCode.CodeQualityAnalysis @@ -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 @@ -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);

65
src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs

@ -131,19 +131,19 @@ namespace ICSharpCode.CodeQualityAnalysis @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -408,15 +409,19 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <param name="methodDefinition">A method definition with instructions</param>
/// <param name="instructions">A collection of instructions</param>
public void ReadInstructions(Method method, MethodDefinition methodDefinition,
Collection<Mono.Cecil.Cil.Instruction> instructions)
Collection<Mono.Cecil.Cil.Instruction> 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 @@ -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 @@ -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);

Loading…
Cancel
Save