Browse Source

add support for properties and add back info text

pull/18/head
Siegfried Pammer 14 years ago
parent
commit
322351adea
  1. 55
      src/AddIns/Analysis/CodeQuality/Engine/AssemblyAnalyzer.cs
  2. 11
      src/AddIns/Analysis/CodeQuality/Engine/Dom/PropertyNode.cs
  3. 20
      src/AddIns/Analysis/CodeQuality/Engine/ILAnalyzer.cs
  4. 12
      src/AddIns/Analysis/CodeQuality/Gui/DependencyMatrixView.xaml.cs
  5. 6
      src/AddIns/Analysis/CodeQuality/Gui/MainView.xaml.cs
  6. 21
      src/AddIns/Analysis/CodeQuality/Gui/NodeDescriptionViewModel.cs
  7. 33
      src/AddIns/Analysis/CodeQuality/Utils/Utils.cs
  8. 42
      src/Main/Base/Project/Src/Util/ScrollUtils.cs

55
src/AddIns/Analysis/CodeQuality/Engine/AssemblyAnalyzer.cs

@ -8,6 +8,7 @@ using System.Linq; @@ -8,6 +8,7 @@ using System.Linq;
using ICSharpCode.CodeQuality.Engine.Dom;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Gui;
using Mono.Cecil;
namespace ICSharpCode.CodeQuality.Engine
@ -24,9 +25,12 @@ namespace ICSharpCode.CodeQuality.Engine @@ -24,9 +25,12 @@ namespace ICSharpCode.CodeQuality.Engine
internal Dictionary<ITypeDefinition, TypeNode> typeMappings;
internal Dictionary<IMethod, MethodNode> methodMappings;
internal Dictionary<IField, FieldNode> fieldMappings;
internal Dictionary<IProperty, PropertyNode> propertyMappings;
internal Dictionary<MemberReference, IEntity> cecilMappings;
List<string> fileNames;
internal IProgressMonitor progressMonitor;
public AssemblyAnalyzer()
{
fileNames = new List<string>();
@ -47,6 +51,7 @@ namespace ICSharpCode.CodeQuality.Engine @@ -47,6 +51,7 @@ namespace ICSharpCode.CodeQuality.Engine
typeMappings = new Dictionary<ITypeDefinition, TypeNode>();
fieldMappings = new Dictionary<IField, FieldNode>();
methodMappings = new Dictionary<IMethod, MethodNode>();
propertyMappings = new Dictionary<IProperty, PropertyNode>();
cecilMappings = new Dictionary<MemberReference, IEntity>();
// first we have to read all types so every method, field or property has a container
@ -70,14 +75,33 @@ namespace ICSharpCode.CodeQuality.Engine @@ -70,14 +75,33 @@ namespace ICSharpCode.CodeQuality.Engine
cecilMappings[cecilObj] = method;
tn.AddChild(node);
}
foreach (var property in type.Properties) {
var node = new PropertyNode(property);
propertyMappings.Add(property, node);
var cecilPropObj = loader.GetCecilObject((IUnresolvedProperty)property.UnresolvedMember);
if (cecilPropObj != null)
cecilMappings[cecilPropObj] = property;
if (property.CanGet) {
var cecilMethodObj = loader.GetCecilObject((IUnresolvedMethod)property.Getter.UnresolvedMember);
if (cecilMethodObj != null)
cecilMappings[cecilMethodObj] = property;
}
if (property.CanSet) {
var cecilMethodObj = loader.GetCecilObject((IUnresolvedMethod)property.Setter.UnresolvedMember);
if (cecilMethodObj != null)
cecilMappings[cecilMethodObj] = property;
}
tn.AddChild(node);
}
}
ILAnalyzer analyzer = new ILAnalyzer(loadedAssemblies.Select(asm => loader.GetCecilObject(asm)).ToArray(), this);
int count = methodMappings.Count + fieldMappings.Count;
int count = methodMappings.Count + fieldMappings.Count + propertyMappings.Count;
int i = 0;
foreach (var element in methodMappings) {
Console.WriteLine("{0} of {1}", ++i, count);
ReportProgress(++i / (double)count);
var cecilObj = loader.GetCecilObject((IUnresolvedMethod)element.Key.UnresolvedMember);
if (cecilObj != null)
analyzer.Analyze(cecilObj.Body, element.Value);
@ -94,16 +118,41 @@ namespace ICSharpCode.CodeQuality.Engine @@ -94,16 +118,41 @@ namespace ICSharpCode.CodeQuality.Engine
}
foreach (var element in fieldMappings) {
Console.WriteLine("{0} of {1}", ++i, count);
ReportProgress(++i / (double)count);
var node = element.Value;
var field = element.Key;
AddRelationshipsForType(node, field.Type);
AddRelationshipsForAttributes(field.Attributes, node);
}
foreach (var element in propertyMappings) {
ReportProgress(++i / (double)count);
var node = element.Value;
var property = element.Key;
if (property.CanGet) {
var cecilObj = loader.GetCecilObject((IUnresolvedMethod)element.Key.Getter.UnresolvedMember);
if (cecilObj != null)
analyzer.Analyze(cecilObj.Body, node);
}
if (property.CanSet) {
var cecilObj = loader.GetCecilObject((IUnresolvedMethod)element.Key.Setter.UnresolvedMember);
if (cecilObj != null)
analyzer.Analyze(cecilObj.Body, node);
}
AddRelationshipsForType(node, property.ReturnType);
AddRelationshipsForAttributes(property.Attributes, node);
}
return new ReadOnlyCollection<AssemblyNode>(assemblyMappings.Values.ToList());
}
void ReportProgress(double progress)
{
if (progressMonitor != null) {
progressMonitor.Progress = progress;
}
}
void AddRelationshipsForTypeParameters(IList<ITypeParameter> typeParameters, NodeBase node)
{
foreach (var param in typeParameters) {

11
src/AddIns/Analysis/CodeQuality/Engine/Dom/PropertyNode.cs

@ -12,10 +12,15 @@ namespace ICSharpCode.CodeQuality.Engine.Dom @@ -12,10 +12,15 @@ namespace ICSharpCode.CodeQuality.Engine.Dom
{
public class PropertyNode : NodeBase
{
public IProperty PropertyDefinition { get; private set; }
public PropertyNode(IProperty propertyDefinition)
{
this.PropertyDefinition = propertyDefinition;
}
public override string Name {
get {
throw new NotImplementedException();
}
get { return PropertyDefinition.PrintFullName(); }
}
public override IList<NodeBase> Children {

20
src/AddIns/Analysis/CodeQuality/Engine/ILAnalyzer.cs

@ -27,31 +27,37 @@ namespace ICSharpCode.CodeQuality.Engine @@ -27,31 +27,37 @@ namespace ICSharpCode.CodeQuality.Engine
this.mappings = mappings;
}
public void Analyze(MethodBody body, MethodNode analyzedMethod)
public void Analyze(MethodBody body, NodeBase analyzedNode)
{
analyzedMethod.CyclomaticComplexity = 0;
if (analyzedNode is MethodNode)
((MethodNode)analyzedNode).CyclomaticComplexity = 0;
if (body == null)
return;
foreach (var instruction in body.Instructions) {
// IL cyclomatic complexity
if (instruction.OpCode.FlowControl == FlowControl.Cond_Branch)
analyzedMethod.CyclomaticComplexity++;
if (instruction.OpCode.FlowControl == FlowControl.Cond_Branch && analyzedNode is MethodNode)
((MethodNode)analyzedNode).CyclomaticComplexity++;
var operand = ReadOperand(instruction);
if (operand is MethodReference) {
var md = ((MethodReference)operand).Resolve();
if (md != null && assemblies.Contains(md.DeclaringType.Module.Assembly) && mappings.cecilMappings.ContainsKey(md)) {
var methodNode = mappings.methodMappings[(IMethod)mappings.cecilMappings[md.Resolve()]];
analyzedMethod.AddRelationship(methodNode);
if (md.IsGetter || md.IsSetter) {
var propertyNode = mappings.propertyMappings[(IProperty)mappings.cecilMappings[md]];
analyzedNode.AddRelationship(propertyNode);
} else {
var methodNode = mappings.methodMappings[(IMethod)mappings.cecilMappings[md]];
analyzedNode.AddRelationship(methodNode);
}
}
} else if (operand is FieldReference) {
var fd = ((FieldReference)operand).Resolve();
if (fd != null && assemblies.Contains(fd.DeclaringType.Module.Assembly) && mappings.cecilMappings.ContainsKey(fd)) {
var fieldNode = mappings.fieldMappings[(IField)mappings.cecilMappings[fd]];
analyzedMethod.AddRelationship(fieldNode);
analyzedNode.AddRelationship(fieldNode);
}
}
}

12
src/AddIns/Analysis/CodeQuality/Gui/DependencyMatrixView.xaml.cs

@ -144,6 +144,7 @@ namespace ICSharpCode.CodeQuality.Gui @@ -144,6 +144,7 @@ namespace ICSharpCode.CodeQuality.Gui
nodeDescriptionViewModel.Node = n.Node;
matrix.HighlightLine(HeaderType.Rows, n.Node);
leftTree.SelectedItem = n;
UpdateInfoText();
}
}
@ -154,6 +155,7 @@ namespace ICSharpCode.CodeQuality.Gui @@ -154,6 +155,7 @@ namespace ICSharpCode.CodeQuality.Gui
nodeDescriptionViewModel.Node = n.Node;
matrix.HighlightLine(HeaderType.Columns, n.Node);
topTree.SelectedItem = n;
UpdateInfoText();
}
}
@ -174,7 +176,15 @@ namespace ICSharpCode.CodeQuality.Gui @@ -174,7 +176,15 @@ namespace ICSharpCode.CodeQuality.Gui
if (e.HoveredCell.ColumnIndex < topTree.Items.Count) {
topTree.SelectedItem = topTree.Items[e.HoveredCell.ColumnIndex + 1];
}
// nodeDescriptionViewModel.Tuple<int, int> = e.HoveredCell.Value;
UpdateInfoText();
}
void UpdateInfoText()
{
var left = leftTree.SelectedItem as MatrixTreeNode;
var top = topTree.SelectedItem as MatrixTreeNode;
if (left != null && top != null)
nodeDescriptionViewModel.InfoText = left.Node.GetInfoText(top.Node);
}
#endregion
}

6
src/AddIns/Analysis/CodeQuality/Gui/MainView.xaml.cs

@ -11,6 +11,7 @@ using System.Windows.Documents; @@ -11,6 +11,7 @@ using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.CodeQuality.Engine;
using ICSharpCode.SharpDevelop.Gui;
using Microsoft.Win32;
namespace ICSharpCode.CodeQuality.Gui
@ -41,12 +42,13 @@ namespace ICSharpCode.CodeQuality.Gui @@ -41,12 +42,13 @@ namespace ICSharpCode.CodeQuality.Gui
return;
context.AddAssemblyFiles(fileDialog.FileNames);
matrix.Update(context.Analyze());
RefreshClick(null, null);
}
void RefreshClick(object sender, RoutedEventArgs e)
{
matrix.Update(context.Analyze());
using (context.progressMonitor = AsynchronousWaitDialog.ShowWaitDialog("Analysis"))
matrix.Update(context.Analyze());
}
}
}

21
src/AddIns/Analysis/CodeQuality/Gui/NodeDescriptionViewModel.cs

@ -28,8 +28,7 @@ namespace ICSharpCode.CodeQuality.Gui @@ -28,8 +28,7 @@ namespace ICSharpCode.CodeQuality.Gui
{
NodeBase node;
public NodeBase Node
{
public NodeBase Node {
get { return node; }
set {
node = value;
@ -43,14 +42,22 @@ namespace ICSharpCode.CodeQuality.Gui @@ -43,14 +42,22 @@ namespace ICSharpCode.CodeQuality.Gui
//
// public int UsesBy {get {return Node.UsedBy.Count();}}
public string ClassType
{
get
{
public string ClassType {
get {
var n = node.GetType().Name;
// Console.WriteLine(n.Substring(0,n.Length -4));
return (n.Substring(0,n.Length -4));
}
}
}
string infoText;
public string InfoText {
get { return infoText; }
set {
infoText = value;
base.RaisePropertyChanged(()=>InfoText);
}
}
}
}

33
src/AddIns/Analysis/CodeQuality/Utils/Utils.cs

@ -5,6 +5,7 @@ using System; @@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using ICSharpCode.CodeQuality.Engine.Dom;
using Mono.Cecil;
namespace ICSharpCode.CodeQuality
@ -12,26 +13,32 @@ namespace ICSharpCode.CodeQuality @@ -12,26 +13,32 @@ namespace ICSharpCode.CodeQuality
/// <summary>
/// Description of Utils.
/// </summary>
public class Utils
public static class Utils
{
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
}
public class AssemblyNameReferenceComparer : IEqualityComparer<AssemblyNameReference>
{
public bool Equals(AssemblyNameReference x, AssemblyNameReference y)
public static string GetInfoText(this NodeBase left, NodeBase top)
{
if (x == y) return true;
if (x != null && y != null)
return x.FullName == y.FullName;
return false;
int item1 = left.GetUses(top);
int item2 = top.GetUses(left);
string text = GetText(item1, item2);
return string.Format("{0} {1} {2}", left.Name, text, top.Name);
}
public int GetHashCode(AssemblyNameReference obj)
static string GetText(int item1, int item2)
{
if (obj == null) return 0;
return obj.FullName.GetHashCode();
if (item1 == -1 && item2 == -1)
return "is the same as";
if (item1 > 0 && item2 > 0)
return "uses and is used by";
if (item1 > 0)
return "uses";
if (item2 > 0)
return "is used by";
return "is not related to";
}
}
}

42
src/Main/Base/Project/Src/Util/ScrollUtils.cs

@ -61,7 +61,7 @@ namespace ICSharpCode.SharpDevelop @@ -61,7 +61,7 @@ namespace ICSharpCode.SharpDevelop
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset);
}
public static void SynchronizeScroll(this ScrollViewer target, ScrollViewer source, ScrollSyncOption option)
public static void SynchronizeScroll(this ScrollViewer target, ScrollViewer source, ScrollSyncOption option, bool proportional = true)
{
if (source == null)
throw new ArgumentNullException("source");
@ -70,31 +70,55 @@ namespace ICSharpCode.SharpDevelop @@ -70,31 +70,55 @@ namespace ICSharpCode.SharpDevelop
double newScrollOffset;
switch (option) {
case ScrollSyncOption.Vertical:
newScrollOffset = source.VerticalOffset / source.ScrollableHeight * target.ScrollableHeight;
if (proportional)
newScrollOffset = source.VerticalOffset / source.ScrollableHeight * target.ScrollableHeight;
else
newScrollOffset = source.VerticalOffset;
target.ScrollToVerticalOffset(double.IsNaN(newScrollOffset) ? 0 : newScrollOffset);
break;
case ScrollSyncOption.Horizontal:
newScrollOffset = source.HorizontalOffset / source.ScrollableWidth * target.ScrollableWidth;
if (proportional)
newScrollOffset = source.HorizontalOffset / source.ScrollableWidth * target.ScrollableWidth;
else
newScrollOffset = source.HorizontalOffset;
target.ScrollToHorizontalOffset(double.IsNaN(newScrollOffset) ? 0 : newScrollOffset);
break;
case ScrollSyncOption.VerticalToHorizontal:
newScrollOffset = source.VerticalOffset / source.ScrollableHeight * target.ScrollableWidth;
if (proportional)
newScrollOffset = source.VerticalOffset / source.ScrollableHeight * target.ScrollableWidth;
else
newScrollOffset = source.VerticalOffset;
target.ScrollToHorizontalOffset(double.IsNaN(newScrollOffset) ? 0 : newScrollOffset);
break;
case ScrollSyncOption.HorizontalToVertical:
newScrollOffset = source.HorizontalOffset / source.ScrollableWidth * target.ScrollableHeight;
if (proportional)
newScrollOffset = source.HorizontalOffset / source.ScrollableWidth * target.ScrollableHeight;
else
newScrollOffset = source.HorizontalOffset;
target.ScrollToVerticalOffset(double.IsNaN(newScrollOffset) ? 0 : newScrollOffset);
break;
case ScrollSyncOption.Both:
newScrollOffset = source.VerticalOffset / source.ScrollableHeight * target.ScrollableHeight;
if (proportional)
newScrollOffset = source.VerticalOffset / source.ScrollableHeight * target.ScrollableHeight;
else
newScrollOffset = source.VerticalOffset;
target.ScrollToVerticalOffset(double.IsNaN(newScrollOffset) ? 0 : newScrollOffset);
newScrollOffset = source.HorizontalOffset / source.ScrollableWidth * target.ScrollableWidth;
if (proportional)
newScrollOffset = source.HorizontalOffset / source.ScrollableWidth * target.ScrollableWidth;
else
newScrollOffset = source.HorizontalOffset;
target.ScrollToHorizontalOffset(double.IsNaN(newScrollOffset) ? 0 : newScrollOffset);
break;
case ScrollSyncOption.BothInterchanged:
newScrollOffset = source.VerticalOffset / source.ScrollableHeight * target.ScrollableWidth;
if (proportional)
newScrollOffset = source.VerticalOffset / source.ScrollableHeight * target.ScrollableWidth;
else
newScrollOffset = source.VerticalOffset;
target.ScrollToHorizontalOffset(double.IsNaN(newScrollOffset) ? 0 : newScrollOffset);
newScrollOffset = source.HorizontalOffset / source.ScrollableWidth * target.ScrollableHeight;
if (proportional)
newScrollOffset = source.HorizontalOffset / source.ScrollableWidth * target.ScrollableHeight;
else
newScrollOffset = source.HorizontalOffset;
target.ScrollToVerticalOffset(double.IsNaN(newScrollOffset) ? 0 : newScrollOffset);
break;
default:

Loading…
Cancel
Save