From 98d36e1175c21e08eda08fe842382e88f749e97e Mon Sep 17 00:00:00 2001 From: Tomas Linhart Date: Fri, 2 Sep 2011 14:50:37 +0200 Subject: [PATCH] DependencyMatrix now calculates some of values. --- .../CodeQuality/CodeQualityAnalysis.csproj | 10 +- .../CodeQuality/CodeQualityAnalysis.sln | 2 +- .../Src/Controls/DependencyMatrix.cs | 11 +- .../Src/Controls/DependencyMatrixControl.cs | 3 +- .../CodeQuality/Src/Controls/MatrixControl.cs | 42 ++++-- .../Src/Controls/TreeMatrixControl.xaml.cs | 3 +- src/AddIns/Analysis/CodeQuality/Src/IValue.cs | 15 ++ .../Analysis/CodeQuality/Src/MainWindow.xaml | 12 +- .../CodeQuality/Src/MainWindow.xaml.cs | 10 +- .../Analysis/CodeQuality/Src/Namespace.cs | 51 +++---- .../Analysis/CodeQuality/Src/Relationship.cs | 18 ++- .../Src/Utility/DoubleKeyDictionary.cs | 138 ++++++++++++++++++ .../CodeQuality/Src/Utility/Matrix.cs | 61 ++++++++ 13 files changed, 308 insertions(+), 68 deletions(-) create mode 100644 src/AddIns/Analysis/CodeQuality/Src/IValue.cs create mode 100644 src/AddIns/Analysis/CodeQuality/Src/Utility/DoubleKeyDictionary.cs create mode 100644 src/AddIns/Analysis/CodeQuality/Src/Utility/Matrix.cs diff --git a/src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj b/src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj index b66b643ae0..ddd9e0ec3c 100644 --- a/src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj +++ b/src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj @@ -120,17 +120,17 @@ - - TreeMatrixControl.xaml Code + TreeMatrixControl.xaml + @@ -139,6 +139,8 @@ + + Designer MSBuild:Compile @@ -243,7 +245,9 @@ Always - + + + @@ -74,7 +81,6 @@ - @@ -147,7 +153,7 @@ - + diff --git a/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs b/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs index 11367374a8..34bcac635d 100644 --- a/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs +++ b/src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs @@ -14,6 +14,7 @@ using System.Windows.Media.Imaging; using GraphSharp.Controls; using ICSharpCode.CodeQualityAnalysis.Controls; +using ICSharpCode.CodeQualityAnalysis.Utility; using Microsoft.Win32; namespace ICSharpCode.CodeQualityAnalysis @@ -72,6 +73,7 @@ namespace ICSharpCode.CodeQualityAnalysis worker.RunWorkerCompleted += (source, args) => { progressBar.Visibility = Visibility.Hidden; assemblyStats.Visibility = Visibility.Visible; + mainTabs.IsEnabled = true; FillMatrix(); }; @@ -93,13 +95,13 @@ namespace ICSharpCode.CodeQualityAnalysis var matrix = new DependencyMatrix(); foreach (var ns in metricsReader.MainModule.Namespaces) { - matrix.HeaderRows.Add(new MatrixCell(ns)); + matrix.HeaderRows.Add(new Cell(ns)); foreach (var type in ns.Types) { - matrix.HeaderRows.Add(new MatrixCell(type)); + matrix.HeaderRows.Add(new Cell(type)); } - matrix.HeaderColumns.Add(new MatrixCell(ns)); + matrix.HeaderColumns.Add(new Cell(ns)); foreach (var type in ns.Types) { - matrix.HeaderColumns.Add(new MatrixCell(type)); + matrix.HeaderColumns.Add(new Cell(type)); } } diff --git a/src/AddIns/Analysis/CodeQuality/Src/Namespace.cs b/src/AddIns/Analysis/CodeQuality/Src/Namespace.cs index c9cb1e9a80..2a9904dc59 100644 --- a/src/AddIns/Analysis/CodeQuality/Src/Namespace.cs +++ b/src/AddIns/Analysis/CodeQuality/Src/Namespace.cs @@ -80,8 +80,7 @@ namespace ICSharpCode.CodeQualityAnalysis foreach (var type in ns.Types) { if (Types.Contains(type)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } } @@ -91,26 +90,23 @@ namespace ICSharpCode.CodeQualityAnalysis Type type = (Type)node; if (this.Types.Contains(type.BaseType)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } foreach (var thisType in type.GenericImplementedInterfacesTypes) { if (this.Types.Contains(thisType)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } foreach (var thisType in type.ImplementedInterfaces) { if (this.Types.Contains(thisType)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } if (this.Types.Contains(type)) { - relationship.Relationships.Add(RelationshipType.Contains); + relationship.AddRelationship(RelationshipType.Contains); } } @@ -118,51 +114,44 @@ namespace ICSharpCode.CodeQualityAnalysis Method method = (Method)node; if (this.Types.Contains(method.ReturnType)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } foreach (var type in method.GenericReturnTypes) { if (this.Types.Contains(type)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } foreach (var parameter in method.Parameters) { if (this.Types.Contains(parameter.ParameterType)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } foreach (var type in parameter.GenericTypes) { if (this.Types.Contains(type)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } } foreach (var type in method.TypeUses) { if (this.Types.Contains(type)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } foreach (var type in method.TypeUses) { if (this.Types.Contains(type)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } foreach (var field in method.FieldUses) { foreach (var type in this.Types) { if (type.Fields.Contains(field)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } } @@ -170,40 +159,36 @@ namespace ICSharpCode.CodeQualityAnalysis foreach (var meth in method.MethodUses) { foreach (var type in this.Types) { if (type.Methods.Contains(meth)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } } foreach (var type in method.TypeUses) { if (this.Types.Contains(type)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } if (this.Types.Contains(method.DeclaringType)) - relationship.Relationships.Add(RelationshipType.Contains); + relationship.AddRelationship(RelationshipType.Contains); } if (node is Field) { Field field = (Field)node; if (this.Types.Contains(field.FieldType)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } foreach (var type in field.GenericTypes) { if (this.Types.Contains(type)) { - relationship.NumberOfOccurrences++; - relationship.Relationships.Add(RelationshipType.UseThis); + relationship.AddRelationship(RelationshipType.UseThis); } } if (this.Types.Contains(field.DeclaringType)) - relationship.Relationships.Add(RelationshipType.Contains); + relationship.AddRelationship(RelationshipType.Contains); } return relationship; diff --git a/src/AddIns/Analysis/CodeQuality/Src/Relationship.cs b/src/AddIns/Analysis/CodeQuality/Src/Relationship.cs index 939cd6c16b..25213474dc 100644 --- a/src/AddIns/Analysis/CodeQuality/Src/Relationship.cs +++ b/src/AddIns/Analysis/CodeQuality/Src/Relationship.cs @@ -10,15 +10,25 @@ namespace ICSharpCode.CodeQualityAnalysis /// /// Description of Relationship. /// - public class Relationship + public class Relationship : IValue { public ISet Relationships { get; private set; } - public int NumberOfOccurrences { get; set; } + + public int OccurrenceCount { get; private set; } + + public string Text { get { return OccurrenceCount.ToString(); } } public Relationship() { Relationships = new HashSet(); - NumberOfOccurrences = 0; + } + + public void AddRelationship(RelationshipType type) + { + if (type == RelationshipType.UseThis) + OccurrenceCount++; + + Relationships.Add(type); } public override string ToString() @@ -28,7 +38,7 @@ namespace ICSharpCode.CodeQualityAnalysis foreach (var relationship in Relationships) builder.Append(relationship + " "); - builder.Append(NumberOfOccurrences); + builder.Append(OccurrenceCount); return builder.ToString(); } } diff --git a/src/AddIns/Analysis/CodeQuality/Src/Utility/DoubleKeyDictionary.cs b/src/AddIns/Analysis/CodeQuality/Src/Utility/DoubleKeyDictionary.cs new file mode 100644 index 0000000000..397d758f86 --- /dev/null +++ b/src/AddIns/Analysis/CodeQuality/Src/Utility/DoubleKeyDictionary.cs @@ -0,0 +1,138 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace ICSharpCode.CodeQualityAnalysis.Utility +{ + public class DoubleKeyDictionary : + IEnumerable>, + IEquatable> + { + private Dictionary innerDictionary; + + public DoubleKeyDictionary() + { + OuterDictionary = new Dictionary>(); + } + + private Dictionary> OuterDictionary { get; set; } + + public void Add(K key1, T key2, V value) + { + if (OuterDictionary.ContainsKey(key1)) { + if (innerDictionary.ContainsKey(key2)) { + OuterDictionary[key1][key2] = value; + } + else { + innerDictionary = OuterDictionary[key1]; + innerDictionary.Add(key2, value); + OuterDictionary[key1] = innerDictionary; + } + } + else { + innerDictionary = new Dictionary(); + innerDictionary[key2] = value; + OuterDictionary.Add(key1, innerDictionary); + } + } + + public V this[K index1, T index2] + { + get + { + Dictionary value1; + OuterDictionary.TryGetValue(index1, out value1); + if (value1 == null) + return default(V); + + V value2; + value1.TryGetValue(index2, out value2); + if (value2 == null) + return default(V); + + return value2; + } + + set + { + Add(index1, index2, value); + } + } + + #region IEnumerable> Members + + public IEnumerator> GetEnumerator() + { + foreach (KeyValuePair> outer in OuterDictionary) + foreach (KeyValuePair inner in outer.Value) + yield return new DoubleKeyPairValue(outer.Key, inner.Key, inner.Value); + } + + #endregion + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #endregion + + #region IEquatable> Members + + public bool Equals(DoubleKeyDictionary other) + { + if (OuterDictionary.Keys.Count != other.OuterDictionary.Keys.Count) + return false; + + bool isEqual = true; + + foreach (KeyValuePair> innerItems in OuterDictionary) { + if (!other.OuterDictionary.ContainsKey(innerItems.Key)) + isEqual = false; + + if (!isEqual) + break; + + // here we can be sure that the key is in both lists, + // but we need to check the contents of the inner dictionary + Dictionary otherInnerDictionary = other.OuterDictionary[innerItems.Key]; + foreach (KeyValuePair innerValue in innerItems.Value) { + if (!otherInnerDictionary.ContainsValue(innerValue.Value)) + isEqual = false; + if (!otherInnerDictionary.ContainsKey(innerValue.Key)) + isEqual = false; + } + + if (!isEqual) + break; + } + + return isEqual; + } + + #endregion + } + + public class DoubleKeyPairValue + { + public K Key1 { get; set; } + public T Key2 { get; set; } + public V Value { get; set; } + + public DoubleKeyPairValue(K key1, T key2, V value) { + Key1 = key1; + Key2 = key2; + Value = value; + } + + public override string ToString() + { + return Key1.ToString() + " - " + Key2.ToString() + " - " + Value.ToString(); + } + } +} diff --git a/src/AddIns/Analysis/CodeQuality/Src/Utility/Matrix.cs b/src/AddIns/Analysis/CodeQuality/Src/Utility/Matrix.cs new file mode 100644 index 0000000000..73fa9bc4f1 --- /dev/null +++ b/src/AddIns/Analysis/CodeQuality/Src/Utility/Matrix.cs @@ -0,0 +1,61 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.CodeQualityAnalysis.Utility +{ + public abstract class Matrix + { + public List> HeaderRows { get; set; } + public List> HeaderColumns { get; set; } + + private DoubleKeyDictionary cache; + + protected Matrix() + { + HeaderRows = new List>(); + HeaderColumns = new List>(); + cache = new DoubleKeyDictionary(); + } + + private TValue GetFromCache(int rowIndex, int columnIndex) + { + return cache[rowIndex, columnIndex]; + } + + private void SaveToCache(int rowIndex, int columnIndex, TValue result) + { + cache.Add(rowIndex, columnIndex, result); + } + + public TValue this[int rowIndex, int columnIndex] + { + get + { + var cacheResult = GetFromCache(rowIndex, columnIndex); + if (cacheResult != null) + return cacheResult; + + var result = GetCellValue(rowIndex, columnIndex); + SaveToCache(rowIndex, columnIndex, result); + return result; + } + } + + protected abstract TValue GetCellValue(int rowIndex, int columnIndex); + } + + public class Cell + { + public TItem Value { get; set; } + + public Cell(TItem value) + { + Value = value; + } + } +}