From 11454252ad5f65009661f1ff8c55017001bd7aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Linhart?= Date: Sun, 8 Aug 2010 17:15:00 +0000 Subject: [PATCH] Added a support for instructions. Assembly stats are now hidden when no assembly is opened. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6386 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../CodeQuality/CodeQualityAnalysis.csproj | 10 +- .../Analysis/CodeQuality/Src/Instruction.cs | 13 + .../Analysis/CodeQuality/Src/MainWindow.xaml | 4 +- .../CodeQuality/Src/MainWindow.xaml.cs | 20 +- src/AddIns/Analysis/CodeQuality/Src/Method.cs | 412 +++++++++--------- .../Analysis/CodeQuality/Src/MetricsReader.cs | 108 ++--- src/AddIns/Analysis/CodeQuality/Src/Module.cs | 7 + 7 files changed, 304 insertions(+), 270 deletions(-) create mode 100644 src/AddIns/Analysis/CodeQuality/Src/Instruction.cs diff --git a/src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj b/src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj index f561b55cdf..6fd1d9b46d 100644 --- a/src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj +++ b/src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj @@ -113,13 +113,13 @@ - - + + Component - - + + Component TreeMatrixControl.xaml Code @@ -127,7 +127,7 @@ - + diff --git a/src/AddIns/Analysis/CodeQuality/Src/Instruction.cs b/src/AddIns/Analysis/CodeQuality/Src/Instruction.cs new file mode 100644 index 0000000000..21b6b7cbf2 --- /dev/null +++ b/src/AddIns/Analysis/CodeQuality/Src/Instruction.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.CodeQualityAnalysis +{ + public class Instruction + { + public Method DeclaringMethod { get; set; } + public string Operand { get; set; } + } +} diff --git a/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml b/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml index 1fd400e086..3e8086718e 100644 --- a/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml +++ b/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml @@ -113,7 +113,7 @@ - + @@ -142,7 +142,7 @@ - + diff --git a/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs b/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs index b8303636ed..94891105ad 100644 --- a/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs +++ b/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs @@ -34,10 +34,10 @@ namespace ICSharpCode.CodeQualityAnalysis private MetricsReader metricsReader; public event PropertyChangedEventHandler PropertyChanged; - public MetricsReader MetricsReader - { + public MetricsReader MetricsReader + { get - { + { return metricsReader; } @@ -54,10 +54,10 @@ namespace ICSharpCode.CodeQualityAnalysis } private void NotifyPropertyChanged(string propertyName) - { - if (PropertyChanged != null) - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } + { + if (PropertyChanged != null) + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } private void btnOpenAssembly_Click(object sender, RoutedEventArgs e) { @@ -72,12 +72,14 @@ namespace ICSharpCode.CodeQualityAnalysis return; progressBar.Visibility = Visibility.Visible; + assemblyStats.Visibility = Visibility.Hidden; fileAssemblyLoading.Text = System.IO.Path.GetFileName(fileDialog.FileName); var worker = new BackgroundWorker(); - worker.DoWork += (source, args) => MetricsReader = new MetricsReader(fileDialog.FileName); - worker.RunWorkerCompleted += (source, args) => { + worker.DoWork += (source, args) => MetricsReader = new MetricsReader(fileDialog.FileName); + worker.RunWorkerCompleted += (source, args) => { progressBar.Visibility = Visibility.Hidden; + assemblyStats.Visibility = Visibility.Visible; FillMatrix(); }; diff --git a/src/AddIns/Analysis/CodeQuality/Src/Method.cs b/src/AddIns/Analysis/CodeQuality/Src/Method.cs index 4443dda32e..292f82e87b 100644 --- a/src/AddIns/Analysis/CodeQuality/Src/Method.cs +++ b/src/AddIns/Analysis/CodeQuality/Src/Method.cs @@ -9,207 +9,213 @@ using QuickGraph; namespace ICSharpCode.CodeQualityAnalysis { - public class Method : INode - { - /// - /// Parameters which are used by method - /// - public ISet Parameters { get; private set; } - - /// - /// Types which are used in body of method - /// - public ISet TypeUses { get; private set; } - - /// - /// Methods which are called in body of method - /// - public ISet MethodUses { get; private set; } - - /// - /// Fields which are accesed in body of method - /// - public ISet FieldUses { get; private set; } - - /// - /// A name of method - /// - public string Name { get; set; } - - /// - /// A return type of method - /// - public Type ReturnType { get; set; } - - /// - /// Type which owns this method - /// - public Type Owner { get; set; } - - /// - /// Whether the method is constructor or not - /// - public bool IsConstructor { get; set; } - - /// - /// Whether the method is public - /// - public bool IsPublic { get; set; } - - /// - /// Whether the method is private - /// - public bool IsPrivate { get; set; } - - /// - /// Whether the method is protected - /// - public bool IsProtected { get; set; } - - /// - /// Whether the method is static - /// - public bool IsStatic { get; set; } - - /// - /// Whether the method is sealed - /// - public bool IsSealed { get; set; } - - /// - /// Whether the method is abstract - /// - public bool IsAbstract { get; set; } - - /// - /// Whether the method is setter - /// - public bool IsSetter { get; set; } - - /// - /// Whether the method is getter - /// - public bool IsGetter { get; set; } - - /// - /// Whether the method is virtual - /// - public bool IsVirtual { get; set; } - - /// - /// If the return type is generic instance so all types used in generic are presented in this set. - /// - public ISet GenericReturnTypes { get; private set; } - - /// - /// Whether the return type is generic instance - /// - public bool IsReturnTypeGenericInstance { get; set; } - - public Method() - { - Parameters = new HashSet(); - - TypeUses = new HashSet(); - MethodUses = new HashSet(); - FieldUses = new HashSet(); - GenericReturnTypes = new HashSet(); - - ReturnType = null; - Owner = null; - - IsReturnTypeGenericInstance = false; - - Dependency = null; - } - - public Relationship GetRelationship(INode node) - { - Relationship relationship = new Relationship(); - return relationship; - } - - public override string ToString() - { - return Name; - } - - public IDependency Dependency { get; set; } - - public string GetInfo() - { - var builder = new StringBuilder(); - builder.AppendLine("Method Summary"); - builder.Append(Environment.NewLine); - builder.AppendLine(String.Format("Name: {0}", Name)); - builder.AppendLine(String.Format("Parameters: {0}", Parameters.Count)); - // more to come - - builder.Append(Environment.NewLine); - - if (IsAbstract) - builder.AppendLine("IsAbstract"); - if (IsConstructor) - builder.AppendLine("IsConstructor"); - if (IsGetter) - builder.AppendLine("IsGetter"); - if (IsSetter) - builder.AppendLine("IsSetter"); - if (IsPrivate) - builder.AppendLine("IsPrivate"); - if (IsProtected) - builder.AppendLine("IsProtected"); - if (IsPublic) - builder.AppendLine("IsPublic"); - if (IsSealed) - builder.AppendLine("IsSealed"); - if (IsStatic) - builder.AppendLine("IsStatic"); - if (IsVirtual) - builder.AppendLine("IsVirtual"); - - return builder.ToString(); - } - - public BitmapSource Icon { get { return NodeIconService.GetIcon(this); } } - } - - public class MethodParameter - { - /// - /// The type of the parameter - /// - public Type ParameterType { get; set; } - - /// - /// Whether the parameter is generic instance - /// - public bool IsGenericInstance { get; set; } - - /// - /// Whether the parameter is in - /// - public bool IsIn { get; set; } - - /// - /// Whether the parameter is out - /// - public bool IsOut { get; set; } - - /// - /// Whether the parameter is optional - /// - public bool IsOptional { get; set; } - - /// - /// If the parameter is generic instance so all types used in generic are presented in this set. - /// - public ISet GenericTypes { get; set; } - - public MethodParameter() - { - GenericTypes = new HashSet(); - IsGenericInstance = false; - } - } + public class Method : INode + { + /// + /// Parameters which are used by method + /// + public ISet Parameters { get; private set; } + + /// + /// Types which are used in body of method + /// + public ISet TypeUses { get; private set; } + + /// + /// Methods which are called in body of method + /// + public ISet MethodUses { get; private set; } + + /// + /// Fields which are accesed in body of method + /// + public ISet FieldUses { get; private set; } + + /// + /// Instructions inside of the method + /// + public ISet Instructions { get; private set; } + + /// + /// A name of method + /// + public string Name { get; set; } + + /// + /// A return type of method + /// + public Type ReturnType { get; set; } + + /// + /// Type which owns this method + /// + public Type Owner { get; set; } + + /// + /// Whether the method is constructor or not + /// + public bool IsConstructor { get; set; } + + /// + /// Whether the method is public + /// + public bool IsPublic { get; set; } + + /// + /// Whether the method is private + /// + public bool IsPrivate { get; set; } + + /// + /// Whether the method is protected + /// + public bool IsProtected { get; set; } + + /// + /// Whether the method is static + /// + public bool IsStatic { get; set; } + + /// + /// Whether the method is sealed + /// + public bool IsSealed { get; set; } + + /// + /// Whether the method is abstract + /// + public bool IsAbstract { get; set; } + + /// + /// Whether the method is setter + /// + public bool IsSetter { get; set; } + + /// + /// Whether the method is getter + /// + public bool IsGetter { get; set; } + + /// + /// Whether the method is virtual + /// + public bool IsVirtual { get; set; } + + /// + /// If the return type is generic instance so all types used in generic are presented in this set. + /// + public ISet GenericReturnTypes { get; private set; } + + /// + /// Whether the return type is generic instance + /// + public bool IsReturnTypeGenericInstance { get; set; } + + public Method() + { + Parameters = new HashSet(); + + TypeUses = new HashSet(); + MethodUses = new HashSet(); + FieldUses = new HashSet(); + Instructions = new HashSet(); + GenericReturnTypes = new HashSet(); + + ReturnType = null; + Owner = null; + + IsReturnTypeGenericInstance = false; + + Dependency = null; + } + + public Relationship GetRelationship(INode node) + { + Relationship relationship = new Relationship(); + return relationship; + } + + public override string ToString() + { + return Name; + } + + public IDependency Dependency { get; set; } + + public string GetInfo() + { + var builder = new StringBuilder(); + builder.AppendLine("Method Summary"); + builder.Append(Environment.NewLine); + builder.AppendLine(String.Format("Name: {0}", Name)); + builder.AppendLine(String.Format("Parameters: {0}", Parameters.Count)); + // more to come + + builder.Append(Environment.NewLine); + + if (IsAbstract) + builder.AppendLine("IsAbstract"); + if (IsConstructor) + builder.AppendLine("IsConstructor"); + if (IsGetter) + builder.AppendLine("IsGetter"); + if (IsSetter) + builder.AppendLine("IsSetter"); + if (IsPrivate) + builder.AppendLine("IsPrivate"); + if (IsProtected) + builder.AppendLine("IsProtected"); + if (IsPublic) + builder.AppendLine("IsPublic"); + if (IsSealed) + builder.AppendLine("IsSealed"); + if (IsStatic) + builder.AppendLine("IsStatic"); + if (IsVirtual) + builder.AppendLine("IsVirtual"); + + return builder.ToString(); + } + + public BitmapSource Icon { get { return NodeIconService.GetIcon(this); } } + } + + public class MethodParameter + { + /// + /// The type of the parameter + /// + public Type ParameterType { get; set; } + + /// + /// Whether the parameter is generic instance + /// + public bool IsGenericInstance { get; set; } + + /// + /// Whether the parameter is in + /// + public bool IsIn { get; set; } + + /// + /// Whether the parameter is out + /// + public bool IsOut { get; set; } + + /// + /// Whether the parameter is optional + /// + public bool IsOptional { get; set; } + + /// + /// If the parameter is generic instance so all types used in generic are presented in this set. + /// + public ISet GenericTypes { get; set; } + + public MethodParameter() + { + GenericTypes = new HashSet(); + IsGenericInstance = false; + } + } } diff --git a/src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs b/src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs index 1f4cfe02b0..cd26ce8694 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; @@ -351,7 +351,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 +378,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 +391,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,36 +408,42 @@ namespace ICSharpCode.CodeQualityAnalysis /// A method definition with instructions /// A collection of instructions public void ReadInstructions(Method method, MethodDefinition methodDefinition, - Collection instructions) + Collection instructions) { - foreach (Instruction instruction in instructions) + foreach (var instruction in instructions) { - var instr = ReadInstruction(instruction); + method.Instructions.Add(new Instruction + { + DeclaringMethod = method, + // Operand = instruction.Operand.ToString() // for now operand as string should be enough + }); - if (instr is MethodDefinition) + var operand = ReadOperand(instruction); + + if (operand is MethodDefinition) { - var md = instr as MethodDefinition; - var type = (from n in method.Owner.Namespace.Module.Namespaces - from t in n.Types - where t.FullName == FormatTypeName(md.DeclaringType, true) - select t).SingleOrDefault(); + var md = operand as MethodDefinition; + var type = (from n in method.Owner.Namespace.Module.Namespaces + 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.Owner) method.MethodUses.Add(findTargetMethod); } - if (instr is FieldDefinition) + if (operand is FieldDefinition) { - var fd = instr as FieldDefinition; + var fd = operand as FieldDefinition; var field = (from f in method.Owner.Fields - where f.Name == fd.Name - select f).SingleOrDefault(); + where f.Name == fd.Name + select f).SingleOrDefault(); if (field != null) method.FieldUses.Add(field); @@ -445,6 +451,25 @@ namespace ICSharpCode.CodeQualityAnalysis } } + /// + /// Reads an instruction operand by recursive calling until non-instruction + /// operand is found + /// + /// An instruction with operand + /// An instruction operand + public object ReadOperand(Mono.Cecil.Cil.Instruction instruction) + { + if (instruction.Operand == null) + return null; + + var nextInstruction = instruction.Operand as Mono.Cecil.Cil.Instruction; + + if (nextInstruction != null) + return ReadOperand(nextInstruction); + + return instruction.Operand; + } + /// /// Reads generic arguments from type and returns them as a set of types /// @@ -473,25 +498,6 @@ namespace ICSharpCode.CodeQualityAnalysis return types; } - /// - /// Reads instruction operand by recursive calling until non-instruction - /// operand is found - /// - /// An instruction with operand - /// An instruction operand - public object ReadInstruction(Instruction instruction) - { - if (instruction.Operand == null) - return null; - - var nextInstruction = instruction.Operand as Instruction; - - if (nextInstruction != null) - return ReadInstruction(nextInstruction); - - return instruction.Operand; - } - /// /// Formats method name by adding parameters to it. If there are not any parameters /// only empty brackers will be added. diff --git a/src/AddIns/Analysis/CodeQuality/Src/Module.cs b/src/AddIns/Analysis/CodeQuality/Src/Module.cs index 7bb242b6c8..c677430b6c 100644 --- a/src/AddIns/Analysis/CodeQuality/Src/Module.cs +++ b/src/AddIns/Analysis/CodeQuality/Src/Module.cs @@ -95,6 +95,13 @@ namespace ICSharpCode.CodeQualityAnalysis } } + public int InstructionsCount + { + get { + return Namespaces.Sum(ns => ns.Types.Sum(type => type.Methods.Sum(method => method.Instructions.Count))); + } + } + public string GetInfo() { var builder = new StringBuilder();