Browse Source

- Tree for browsing has been rewritten to XAML. It allows nice styling options.

- Collection's properties got private setter.
- First draft of Dependency Matrix which uses a tree.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6251 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Tomáš Linhart 16 years ago
parent
commit
737c524a7c
  1. 18
      src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj
  2. 38
      src/AddIns/Analysis/CodeQuality/Src/Controls/TreeMatrixControl.xaml
  3. 101
      src/AddIns/Analysis/CodeQuality/Src/Controls/TreeMatrixControl.xaml.cs
  4. 4
      src/AddIns/Analysis/CodeQuality/Src/Event.cs
  5. 7
      src/AddIns/Analysis/CodeQuality/Src/Field.cs
  6. 2
      src/AddIns/Analysis/CodeQuality/Src/INode.cs
  7. 141
      src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml
  8. 426
      src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs
  9. 15
      src/AddIns/Analysis/CodeQuality/Src/Method.cs
  10. 19
      src/AddIns/Analysis/CodeQuality/Src/MetricsReader.cs
  11. 6
      src/AddIns/Analysis/CodeQuality/Src/Module.cs
  12. 6
      src/AddIns/Analysis/CodeQuality/Src/Namespace.cs
  13. 29
      src/AddIns/Analysis/CodeQuality/Src/Type.cs

18
src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj

@ -38,19 +38,6 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<OutputPath>bin\Debug\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<OutputPath>bin\Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
@ -128,6 +115,10 @@
<Compile Include="Src\Controls\DependencyVertex.cs" /> <Compile Include="Src\Controls\DependencyVertex.cs" />
<Compile Include="Src\Controls\Matrix.cs" /> <Compile Include="Src\Controls\Matrix.cs" />
<Compile Include="Src\Controls\MatrixControl.cs" /> <Compile Include="Src\Controls\MatrixControl.cs" />
<Compile Include="Src\Controls\TreeMatrixControl.xaml.cs">
<DependentUpon>TreeMatrixControl.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Src\DependencyGraphCommand.cs" /> <Compile Include="Src\DependencyGraphCommand.cs" />
<Compile Include="Src\Event.cs" /> <Compile Include="Src\Event.cs" />
<Compile Include="Src\Field.cs" /> <Compile Include="Src\Field.cs" />
@ -144,6 +135,7 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Src\Controls\TreeMatrixControl.xaml" />
<Page Include="Src\MainWindow.xaml"> <Page Include="Src\MainWindow.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>

38
src/AddIns/Analysis/CodeQuality/Src/Controls/TreeMatrixControl.xaml

@ -0,0 +1,38 @@
<UserControl x:Class="ICSharpCode.CodeQualityAnalysis.Controls.TreeMatrixControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:ICSharpCode.CodeQualityAnalysis.Controls">
<UserControl.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="Header" Value="test" />
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TreeView Name="leftTree" Grid.Row="1" Grid.Column="0">
<TreeView.Resources>
</TreeView.Resources>
</TreeView>
<TreeView Name="topTree" Grid.Row="0" Grid.Column="1">
<TreeView.LayoutTransform>
<RotateTransform Angle="-90" />
</TreeView.LayoutTransform>
</TreeView>
<WindowsFormsHost Grid.Column="1" Grid.Row="1">
<Controls:DependencyMatrixControl x:Name="matrixControl"></Controls:DependencyMatrixControl>
</WindowsFormsHost>
</Grid>
</UserControl>

101
src/AddIns/Analysis/CodeQuality/Src/Controls/TreeMatrixControl.xaml.cs

@ -0,0 +1,101 @@
/*
* Created by SharpDevelop.
* User: Tomas
* Date: 26.7.2010
* Time: 10:08
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Forms;
namespace ICSharpCode.CodeQualityAnalysis.Controls
{
/// <summary>
/// Interaction logic for TreeMatrixControl.xaml
/// </summary>
public partial class TreeMatrixControl : System.Windows.Controls.UserControl
{
public Matrix<INode> Matrix
{
get
{
return matrixControl.Matrix;
}
set
{
matrixControl.Matrix = value;
}
}
public TreeMatrixControl()
{
InitializeComponent();
matrixControl.RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
matrixControl.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
matrixControl.BorderStyle = BorderStyle.FixedSingle;
matrixControl.RowHeadersVisible = false;
matrixControl.ColumnHeadersVisible = false;
}
public void DrawMatrix()
{
matrixControl.DrawMatrix();
}
public void DrawTree(Module module)
{
foreach (var ns in module.Namespaces)
{
var nsType = new TreeViewItem
{
Header = ns.Name
};
leftTree.Items.Add(nsType);
foreach (var type in ns.Types)
{
var itemType = new TreeViewItem
{
Header = type.Name
};
nsType.Items.Add(itemType);
foreach (var method in type.Methods)
{
var itemMethod = new TreeViewItem
{
Header = method.Name
};
itemType.Items.Add(itemMethod);
}
foreach (var field in type.Fields)
{
var itemField = new TreeViewItem
{
Header = field.Name
};
itemType.Items.Add(itemField);
}
}
}
}
}
}

4
src/AddIns/Analysis/CodeQuality/Src/Event.cs

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
using QuickGraph; using QuickGraph;
namespace ICSharpCode.CodeQualityAnalysis namespace ICSharpCode.CodeQualityAnalysis
@ -46,5 +48,7 @@ namespace ICSharpCode.CodeQualityAnalysis
// Events aren't visible. They are showed like fields instead. // Events aren't visible. They are showed like fields instead.
return this.ToString(); return this.ToString();
} }
public BitmapSource Icon { get { return null; } }
} }
} }

7
src/AddIns/Analysis/CodeQuality/Src/Field.cs

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
using QuickGraph; using QuickGraph;
namespace ICSharpCode.CodeQualityAnalysis namespace ICSharpCode.CodeQualityAnalysis
@ -66,13 +68,14 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <summary> /// <summary>
/// If the field has generic instance so all types used in generic are presented in this set. /// If the field has generic instance so all types used in generic are presented in this set.
/// </summary> /// </summary>
public ISet<Type> GenericTypes { get; set; } public ISet<Type> GenericTypes { get; private set; }
public Field() public Field()
{ {
FieldType = null; FieldType = null;
IsEvent = false; IsEvent = false;
Owner = null; Owner = null;
GenericTypes = new HashSet<Type>();
Dependency = null; Dependency = null;
} }
@ -117,5 +120,7 @@ namespace ICSharpCode.CodeQualityAnalysis
return builder.ToString(); return builder.ToString();
} }
public BitmapSource Icon { get { return NodeIconService.GetIcon(this); } }
} }
} }

2
src/AddIns/Analysis/CodeQuality/Src/INode.cs

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
namespace ICSharpCode.CodeQualityAnalysis namespace ICSharpCode.CodeQualityAnalysis
{ {
@ -11,5 +12,6 @@ namespace ICSharpCode.CodeQualityAnalysis
IDependency Dependency { set; get; } IDependency Dependency { set; get; }
string GetInfo(); string GetInfo();
Relationship GetRelationship(INode node); Relationship GetRelationship(INode node);
BitmapSource Icon { get; }
} }
} }

141
src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml

@ -3,58 +3,95 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:ICSharpCode.WpfDesign.Designer.Controls;assembly=ICSharpCode.WpfDesign.Designer" xmlns:Controls="clr-namespace:ICSharpCode.WpfDesign.Designer.Controls;assembly=ICSharpCode.WpfDesign.Designer"
xmlns:Graph="clr-namespace:ICSharpCode.CodeQualityAnalysis.Controls" xmlns:Graph="clr-namespace:ICSharpCode.CodeQualityAnalysis.Controls"
xmlns:src="clr-namespace:ICSharpCode.CodeQualityAnalysis"
Title="Code Quality Analysis" Title="Code Quality Analysis"
x:Name="root"> x:Name="root">
<Window.Resources> <Window.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources/GraphTemplate.xaml" /> <ResourceDictionary Source="../Resources/GraphTemplate.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources> <DataTemplate x:Key="MemberTemplate">
<StackPanel Orientation="Horizontal">
<TabControl> <Image Source="{Binding Path=Icon}" Margin="0, 0, 0, 3" />
<TabItem Header="Dependency Graph"> <TextBlock Text="{Binding Path=Name}" />
<Grid> </StackPanel>
<Grid.RowDefinitions> </DataTemplate>
<RowDefinition Height="Auto" />
<RowDefinition /> <HierarchicalDataTemplate x:Key="TypeTemplate"
</Grid.RowDefinitions> ItemTemplate="{StaticResource MemberTemplate}"
ItemsSource="{Binding Members}">
<Grid.ColumnDefinitions> <StackPanel Orientation="Horizontal">
<ColumnDefinition Width="250px" /> <Image Source="{Binding Path=Icon}" />
<ColumnDefinition /> <TextBlock Text="{Binding Path=Name}" />
<ColumnDefinition Width="200px" /> </StackPanel>
</Grid.ColumnDefinitions> </HierarchicalDataTemplate>
<ToolBarTray Background="White" Grid.Row="0" Grid.ColumnSpan="2"> <HierarchicalDataTemplate x:Key="NamespaceTemplate"
<ToolBar> ItemsSource="{Binding Types}"
<Button Name="btnOpenAssembly" Click="btnOpenAssembly_Click" Margin="0 0 5 0">Open Assembly</Button> ItemTemplate="{StaticResource TypeTemplate}">
<Button Name="btnRelayout" Click="btnRelayout_Click" Margin="0 0 5 0">Relayout</Button> <StackPanel Orientation="Horizontal">
<Button Name="btnContinueLayout" Click="btnContinueLayout_Click" Margin="0 0 5 0">Continue Layout</Button> <Image Source="{Binding Path=Icon}" />
<Button Name="btnResetGraph" Click="btnResetGraph_Click" Margin="0 0 5 0">Reset Graph</Button> <TextBlock Text="{Binding Path=Name}" />
<Button Name="btnSaveImageGraph" Click="btnSaveImageGraph_Click">Save an Image of Graph</Button> </StackPanel>
</ToolBar> </HierarchicalDataTemplate>
</ToolBarTray>
<HierarchicalDataTemplate ItemsSource="{Binding Namespaces}"
<TreeView Name="definitionTree" Grid.Row="1" Grid.Column="0" SelectedItemChanged="definitionTree_SelectedItemChanged" /> ItemTemplate="{StaticResource NamespaceTemplate}"
x:Key="ModuleTemplate">
<Controls:ZoomControl Grid.Row="1" Grid.Column="1" Name="zoom" AlwaysShowZoomButtons="True" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible"> <StackPanel Orientation="Horizontal">
<Graph:DependencyGraphLayout x:Name="graphLayout" <Image Source="{Binding Path=Icon}" />
LayoutAlgorithmType="LinLog" <TextBlock Text="{Binding Path=Name}" />
OverlapRemovalAlgorithmType="FSA" </StackPanel>
HighlightAlgorithmType="Simple" </HierarchicalDataTemplate>
VertexClick="graphLayout_VertexClick" </ResourceDictionary>
/> </Window.Resources>
</Controls:ZoomControl>
<TabControl>
<TextBlock Name="txbTypeInfo" Grid.Column="3" Grid.Row="1"/> <TabItem Header="Dependency Graph">
</Grid> <Grid>
</TabItem> <Grid.RowDefinitions>
<TabItem Header="Dependency Matrix"> <RowDefinition Height="Auto" />
<WindowsFormsHost> <RowDefinition />
<Graph:DependencyMatrixControl x:Name="matrixControl"></Graph:DependencyMatrixControl> </Grid.RowDefinitions>
</WindowsFormsHost>
</TabItem> <Grid.ColumnDefinitions>
</TabControl> <ColumnDefinition Width="250px" />
<ColumnDefinition />
<ColumnDefinition Width="200px" />
</Grid.ColumnDefinitions>
<ToolBarTray Background="White" Grid.Row="0" Grid.ColumnSpan="2">
<ToolBar>
<Button Name="btnOpenAssembly" Click="btnOpenAssembly_Click" Margin="0 0 5 0">Open Assembly</Button>
<Button Name="btnRelayout" Click="btnRelayout_Click" Margin="0 0 5 0">Relayout</Button>
<Button Name="btnContinueLayout" Click="btnContinueLayout_Click" Margin="0 0 5 0">Continue Layout</Button>
<Button Name="btnResetGraph" Click="btnResetGraph_Click" Margin="0 0 5 0">Reset Graph</Button>
<Button Name="btnSaveImageGraph" Click="btnSaveImageGraph_Click">Save an Image of Graph</Button>
</ToolBar>
</ToolBarTray>
<TreeView Name="definitionTree" Grid.Row="1" Grid.Column="0"
SelectedItemChanged="definitionTree_SelectedItemChanged"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ModuleTemplate}">
</TreeView>
<Controls:ZoomControl Grid.Row="1" Grid.Column="1" Name="zoom" AlwaysShowZoomButtons="True" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
<Graph:DependencyGraphLayout x:Name="graphLayout"
LayoutAlgorithmType="LinLog"
OverlapRemovalAlgorithmType="FSA"
HighlightAlgorithmType="Simple"
VertexClick="graphLayout_VertexClick"
/>
</Controls:ZoomControl>
<TextBlock Name="txbTypeInfo" Grid.Column="3" Grid.Row="1"/>
</Grid>
</TabItem>
<TabItem Header="Dependency Matrix">
<Graph:TreeMatrixControl x:Name="matrixControl"></Graph:TreeMatrixControl>
</TabItem>
</TabControl>
</Window> </Window>

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

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -12,6 +13,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using GraphSharp.Controls; using GraphSharp.Controls;
using ICSharpCode.CodeQualityAnalysis.Controls; using ICSharpCode.CodeQualityAnalysis.Controls;
using ICSharpCode.Core.Presentation; using ICSharpCode.Core.Presentation;
@ -24,271 +26,167 @@ using QuickGraph.Collections;
namespace ICSharpCode.CodeQualityAnalysis namespace ICSharpCode.CodeQualityAnalysis
{ {
/// <summary> /// <summary>
/// Interaction logic for MainWindow.xaml /// Interaction logic for MainWindow.xaml
/// </summary> /// </summary>
public partial class MainWindow : Window public partial class MainWindow : Window, INotifyPropertyChanged
{ {
private MetricsReader _metricsReader; private MetricsReader metricsReader;
public event PropertyChangedEventHandler PropertyChanged;
public MainWindow()
{ public MetricsReader MetricsReader
InitializeComponent(); {
} get
{
private void btnOpenAssembly_Click(object sender, RoutedEventArgs e) return metricsReader;
{ }
var fileDialog = new OpenFileDialog
{ set
Filter = "Component Files (*.dll, *.exe)|*.dll;*.exe" {
}; metricsReader = value;
NotifyPropertyChanged("MetricsReader");
fileDialog.ShowDialog(); }
}
if (String.IsNullOrEmpty(fileDialog.FileName))
return; public MainWindow()
{
definitionTree.Items.Clear(); InitializeComponent();
}
_metricsReader = new MetricsReader(fileDialog.FileName);
private void NotifyPropertyChanged(string propertyName)
FillTree();
FillMatrix();
}
private void btnRelayout_Click(object sender, RoutedEventArgs e)
{
graphLayout.Relayout();
}
private void btnContinueLayout_Click(object sender, RoutedEventArgs e)
{
graphLayout.ContinueLayout();
}
/// <summary>
/// Fill tree with module, types and methods and fields
/// </summary>
private void FillTree()
{ {
var itemModule = new MetricTreeViewItem if (PropertyChanged != null)
{ PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
Text = _metricsReader.MainModule.Name,
Dependency = _metricsReader.MainModule,
Icon = NodeIconService.GetIcon(_metricsReader.MainModule)
};
definitionTree.Items.Add(itemModule);
foreach (var ns in _metricsReader.MainModule.Namespaces)
{
var nsType = new MetricTreeViewItem
{
Text = ns.Name,
Dependency = ns,
Icon = NodeIconService.GetIcon(ns)
};
itemModule.Items.Add(nsType);
foreach (var type in ns.Types)
{
var itemType = new MetricTreeViewItem
{
Text = type.Name,
Dependency = type,
Icon = NodeIconService.GetIcon(type)
};
nsType.Items.Add(itemType);
foreach (var method in type.Methods)
{
var itemMethod = new MetricTreeViewItem
{
Text = method.Name,
Dependency = null,
Icon = NodeIconService.GetIcon(method)
};
itemType.Items.Add(itemMethod);
}
foreach (var field in type.Fields)
{
var itemField = new MetricTreeViewItem
{
Text = field.Name,
Dependency = null,
Icon = NodeIconService.GetIcon(field)
};
itemType.Items.Add(itemField);
}
}
}
} }
private void FillMatrix() private void btnOpenAssembly_Click(object sender, RoutedEventArgs e)
{ {
var matrix = new DependencyMatrix(); var fileDialog = new OpenFileDialog
{
foreach (var ns in _metricsReader.MainModule.Namespaces) { Filter = "Component Files (*.dll, *.exe)|*.dll;*.exe"
matrix.HeaderRows.Add(new MatrixCell<INode>(ns)); };
foreach (var type in ns.Types) {
matrix.HeaderRows.Add(new MatrixCell<INode>(type)); fileDialog.ShowDialog();
}
matrix.HeaderColumns.Add(new MatrixCell<INode>(ns)); if (String.IsNullOrEmpty(fileDialog.FileName))
foreach (var type in ns.Types) { return;
matrix.HeaderColumns.Add(new MatrixCell<INode>(type));
} definitionTree.Items.Clear();
}
MetricsReader = new MetricsReader(fileDialog.FileName);
matrixControl.Matrix = matrix; definitionTree.ItemsSource = metricsReader.Modules;
matrixControl.DrawMatrix();
} FillMatrix();
}
private void definitionTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{ private void btnRelayout_Click(object sender, RoutedEventArgs e)
var item = definitionTree.SelectedItem as MetricTreeViewItem; {
graphLayout.Relayout();
if (item != null && item.Dependency != null) }
{
var graph = item.Dependency.BuildDependencyGraph(); private void btnContinueLayout_Click(object sender, RoutedEventArgs e)
graphLayout.ChangeGraph(graph); {
} graphLayout.ContinueLayout();
} }
private void graphLayout_VertexClick(object sender, MouseButtonEventArgs e) private void FillMatrix()
{ {
var vertexControl = sender as VertexControl; var matrix = new DependencyMatrix();
if (vertexControl != null)
{ foreach (var ns in metricsReader.MainModule.Namespaces) {
var vertex = vertexControl.Vertex as DependencyVertex; matrix.HeaderRows.Add(new MatrixCell<INode>(ns));
if (vertex != null) foreach (var type in ns.Types) {
{ matrix.HeaderRows.Add(new MatrixCell<INode>(type));
txbTypeInfo.Text = vertex.Node.GetInfo(); }
} matrix.HeaderColumns.Add(new MatrixCell<INode>(ns));
} foreach (var type in ns.Types) {
} matrix.HeaderColumns.Add(new MatrixCell<INode>(type));
}
private void btnResetGraph_Click(object sender, RoutedEventArgs e) }
{
graphLayout.ResetGraph(); matrixControl.Matrix = matrix;
} matrixControl.DrawMatrix();
matrixControl.DrawTree(metricsReader.MainModule);
private void btnSaveImageGraph_Click(object sender, RoutedEventArgs e) }
{
var fileDialog = new SaveFileDialog() private void definitionTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{ {
Filter = "PNG (*.png)|*.png|JPEG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|TIFF (.tiff)|*.tiff" var item = definitionTree.SelectedItem as INode;
};
if (item != null && item.Dependency != null)
fileDialog.ShowDialog(); {
var graph = item.Dependency.BuildDependencyGraph();
if (String.IsNullOrEmpty(fileDialog.FileName)) graphLayout.ChangeGraph(graph);
return; }
}
// render it
var renderBitmap = new RenderTargetBitmap((int)graphLayout.ActualWidth, private void graphLayout_VertexClick(object sender, MouseButtonEventArgs e)
(int)graphLayout.ActualHeight, {
96d, var vertexControl = sender as VertexControl;
96d, if (vertexControl != null)
PixelFormats.Default); {
renderBitmap.Render(graphLayout); var vertex = vertexControl.Vertex as DependencyVertex;
if (vertex != null)
using (var outStream = new FileStream(fileDialog.FileName, FileMode.Create)) {
{ txbTypeInfo.Text = vertex.Node.GetInfo();
BitmapEncoder encoder; }
}
switch (fileDialog.FilterIndex) }
{
case 1: private void btnResetGraph_Click(object sender, RoutedEventArgs e)
encoder = new PngBitmapEncoder(); {
break; graphLayout.ResetGraph();
case 2: }
encoder = new JpegBitmapEncoder();
break; private void btnSaveImageGraph_Click(object sender, RoutedEventArgs e)
case 3: {
encoder = new GifBitmapEncoder(); var fileDialog = new SaveFileDialog()
break; {
case 4: Filter = "PNG (*.png)|*.png|JPEG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|TIFF (.tiff)|*.tiff"
encoder = new BmpBitmapEncoder(); };
break;
case 5: fileDialog.ShowDialog();
encoder = new TiffBitmapEncoder();
break; if (String.IsNullOrEmpty(fileDialog.FileName))
default: return;
encoder = new PngBitmapEncoder();
break; // render it
} var renderBitmap = new RenderTargetBitmap((int)graphLayout.ActualWidth,
(int)graphLayout.ActualHeight,
encoder.Frames.Add(BitmapFrame.Create(renderBitmap)); 96d,
encoder.Save(outStream); 96d,
} PixelFormats.Default);
} renderBitmap.Render(graphLayout);
private class MetricTreeViewItem : TreeViewItem using (var outStream = new FileStream(fileDialog.FileName, FileMode.Create))
{ {
private readonly Image _iconControl; BitmapEncoder encoder;
private readonly TextBlock _textControl;
private BitmapSource _bitmap; switch (fileDialog.FilterIndex)
{
public IDependency Dependency { get; set; } case 1:
encoder = new PngBitmapEncoder();
/// <summary> break;
/// Gets or sets the text content for the item case 2:
/// </summary> encoder = new JpegBitmapEncoder();
public string Text break;
{ case 3:
get encoder = new GifBitmapEncoder();
{ break;
return _textControl.Text; case 4:
} encoder = new BmpBitmapEncoder();
set break;
{ case 5:
_textControl.Text = value; encoder = new TiffBitmapEncoder();
} break;
} default:
encoder = new PngBitmapEncoder();
/// <summary> break;
/// Gets or sets the icon for the item }
/// </summary>
public BitmapSource Icon encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
{ encoder.Save(outStream);
get }
{ }
return _bitmap; }
}
set
{
_iconControl.Source = _bitmap = value;
}
}
public MetricTreeViewItem()
{
var stack = new StackPanel
{
Orientation = Orientation.Horizontal
};
Header = stack;
_iconControl = new Image
{
Margin = new Thickness(0, 0, 5, 0)
};
_textControl = new TextBlock()
{
VerticalAlignment = VerticalAlignment.Center
};
stack.Children.Add(_iconControl);
stack.Children.Add(_textControl);
}
}
}
} }

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

@ -1,7 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
using QuickGraph; using QuickGraph;
namespace ICSharpCode.CodeQualityAnalysis namespace ICSharpCode.CodeQualityAnalysis
@ -11,22 +14,22 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <summary> /// <summary>
/// Parameters which are used by method /// Parameters which are used by method
/// </summary> /// </summary>
public ISet<MethodParameter> Parameters { get; set; } public ISet<MethodParameter> Parameters { get; private set; }
/// <summary> /// <summary>
/// Types which are used in body of method /// Types which are used in body of method
/// </summary> /// </summary>
public ISet<Type> TypeUses { get; set; } public ISet<Type> TypeUses { get; private set; }
/// <summary> /// <summary>
/// Methods which are called in body of method /// Methods which are called in body of method
/// </summary> /// </summary>
public ISet<Method> MethodUses { get; set; } public ISet<Method> MethodUses { get; private set; }
/// <summary> /// <summary>
/// Fields which are accesed in body of method /// Fields which are accesed in body of method
/// </summary> /// </summary>
public ISet<Field> FieldUses { get; set; } public ISet<Field> FieldUses { get; private set; }
/// <summary> /// <summary>
/// A name of method /// A name of method
@ -96,7 +99,7 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <summary> /// <summary>
/// If the return type is generic instance so all types used in generic are presented in this set. /// If the return type is generic instance so all types used in generic are presented in this set.
/// </summary> /// </summary>
public ISet<Type> GenericReturnTypes { get; set; } public ISet<Type> GenericReturnTypes { get; private set; }
/// <summary> /// <summary>
/// Whether the return type is generic instance /// Whether the return type is generic instance
@ -167,6 +170,8 @@ namespace ICSharpCode.CodeQualityAnalysis
return builder.ToString(); return builder.ToString();
} }
public BitmapSource Icon { get { return NodeIconService.GetIcon(this); } }
} }
public class MethodParameter public class MethodParameter

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

@ -16,10 +16,12 @@ namespace ICSharpCode.CodeQualityAnalysis
IDictionary<MemberReference, string> nameCache; IDictionary<MemberReference, string> nameCache;
public Module MainModule { get; private set; } public Module MainModule { get; private set; }
public ISet<Module> Modules { get; private set; }
public MetricsReader(string file) public MetricsReader(string file)
{ {
nameCache = new Dictionary<MemberReference, string>(); nameCache = new Dictionary<MemberReference, string>();
Modules = new HashSet<Module>();
ReadAssembly(file); ReadAssembly(file);
} }
@ -31,6 +33,7 @@ namespace ICSharpCode.CodeQualityAnalysis
{ {
var assembly = AssemblyDefinition.ReadAssembly(file); var assembly = AssemblyDefinition.ReadAssembly(file);
ReadModule(assembly.MainModule); ReadModule(assembly.MainModule);
// support for additional modules but never seen assembly with more than one
} }
/// <summary> /// <summary>
@ -39,11 +42,13 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <param name="moduleDefinition">A module which contains information</param> /// <param name="moduleDefinition">A module which contains information</param>
private void ReadModule(ModuleDefinition moduleDefinition) private void ReadModule(ModuleDefinition moduleDefinition)
{ {
this.MainModule = new Module() MainModule = new Module()
{ {
Name = moduleDefinition.Name Name = moduleDefinition.Name
}; };
Modules.Add(MainModule);
if (moduleDefinition.HasTypes) if (moduleDefinition.HasTypes)
ReadTypes(MainModule, moduleDefinition.Types); ReadTypes(MainModule, moduleDefinition.Types);
} }
@ -183,8 +188,8 @@ namespace ICSharpCode.CodeQualityAnalysis
if (typeDefinition.BaseType.IsGenericInstance) if (typeDefinition.BaseType.IsGenericInstance)
{ {
type.IsBaseTypeGenericInstance = true; type.IsBaseTypeGenericInstance = true;
type.GenericBaseTypes = ReadGenericArguments(type.Namespace.Module, type.GenericBaseTypes.UnionWith(ReadGenericArguments(type.Namespace.Module,
(GenericInstanceType)typeDefinition.BaseType); (GenericInstanceType)typeDefinition.BaseType));
} }
} }
@ -298,8 +303,8 @@ namespace ICSharpCode.CodeQualityAnalysis
if (fieldDefinition.FieldType.IsGenericInstance) if (fieldDefinition.FieldType.IsGenericInstance)
{ {
field.IsGenericInstance = true; field.IsGenericInstance = true;
field.GenericTypes = ReadGenericArguments(type.Namespace.Module, field.GenericTypes.UnionWith(ReadGenericArguments(type.Namespace.Module,
(GenericInstanceType)fieldDefinition.FieldType); (GenericInstanceType)fieldDefinition.FieldType));
} }
field.FieldType = fieldType; field.FieldType = fieldType;
@ -342,8 +347,8 @@ namespace ICSharpCode.CodeQualityAnalysis
if (methodDefinition.ReturnType.IsGenericInstance) if (methodDefinition.ReturnType.IsGenericInstance)
{ {
method.IsReturnTypeGenericInstance = true; method.IsReturnTypeGenericInstance = true;
method.GenericReturnTypes = ReadGenericArguments(type.Namespace.Module, method.GenericReturnTypes.UnionWith(ReadGenericArguments(type.Namespace.Module,
(GenericInstanceType) methodDefinition.ReturnType); (GenericInstanceType) methodDefinition.ReturnType));
} }
// reading types from parameters // reading types from parameters

6
src/AddIns/Analysis/CodeQuality/Src/Module.cs

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
using ICSharpCode.CodeQualityAnalysis.Controls; using ICSharpCode.CodeQualityAnalysis.Controls;
using QuickGraph; using QuickGraph;
@ -14,7 +16,7 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <summary> /// <summary>
/// Namespaces within module /// Namespaces within module
/// </summary> /// </summary>
public ISet<Namespace> Namespaces { get; set; } public ISet<Namespace> Namespaces { get; private set; }
/// <summary> /// <summary>
/// Name of module /// Name of module
@ -86,5 +88,7 @@ namespace ICSharpCode.CodeQualityAnalysis
return builder.ToString(); return builder.ToString();
} }
public BitmapSource Icon { get { return NodeIconService.GetIcon(this); } }
} }
} }

6
src/AddIns/Analysis/CodeQuality/Src/Namespace.cs

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
using ICSharpCode.CodeQualityAnalysis.Controls; using ICSharpCode.CodeQualityAnalysis.Controls;
using QuickGraph; using QuickGraph;
@ -14,7 +16,7 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <summary> /// <summary>
/// Types within namespace /// Types within namespace
/// </summary> /// </summary>
public ISet<Type> Types { get; set; } public ISet<Type> Types { get; private set; }
/// <summary> /// <summary>
/// Name of namespace /// Name of namespace
@ -224,5 +226,7 @@ namespace ICSharpCode.CodeQualityAnalysis
return builder.ToString(); return builder.ToString();
} }
public BitmapSource Icon { get { return NodeIconService.GetIcon(this); } }
} }
} }

29
src/AddIns/Analysis/CodeQuality/Src/Type.cs

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Media.Imaging;
using ICSharpCode.CodeQualityAnalysis.Controls; using ICSharpCode.CodeQualityAnalysis.Controls;
using QuickGraph; using QuickGraph;
@ -14,7 +16,7 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <summary> /// <summary>
/// Nested types like inner classes, interfaces and so on. /// Nested types like inner classes, interfaces and so on.
/// </summary> /// </summary>
public ISet<Type> NestedTypes { get; set; } public ISet<Type> NestedTypes { get; private set; }
/// <summary> /// <summary>
/// Type which owns this type. If this isn't nested type so Owner is null. /// Type which owns this type. If this isn't nested type so Owner is null.
@ -29,22 +31,33 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <summary> /// <summary>
/// Interfaces which are implemented by this type /// Interfaces which are implemented by this type
/// </summary> /// </summary>
public ISet<Type> ImplementedInterfaces { get; set; } public ISet<Type> ImplementedInterfaces { get; private set; }
/// <summary> /// <summary>
/// Methods within type /// Methods within type
/// </summary> /// </summary>
public ISet<Method> Methods { get; set; } public ISet<Method> Methods { get; private set; }
/// <summary> /// <summary>
/// Fields within type /// Fields within type
/// </summary> /// </summary>
public ISet<Field> Fields { get; set; } public ISet<Field> Fields { get; private set; }
/// <summary>
/// Members of type such as methods and fields
/// </summary>
public IEnumerable<INode> Members
{
get
{
return new HashSet<INode>(Methods).Union(Fields);
}
}
/// <summary> /// <summary>
/// Events within type /// Events within type
/// </summary> /// </summary>
public ISet<Event> Events { get; set; } public ISet<Event> Events { get; private set; }
/// <summary> /// <summary>
/// Name of type with a name of namespace. /// Name of type with a name of namespace.
@ -135,12 +148,12 @@ namespace ICSharpCode.CodeQualityAnalysis
/// <summary> /// <summary>
/// If the base type is generic instance so all types used in generic are presented in this set. /// If the base type is generic instance so all types used in generic are presented in this set.
/// </summary> /// </summary>
public ISet<Type> GenericBaseTypes { get; set; } public ISet<Type> GenericBaseTypes { get; private set; }
/// <summary> /// <summary>
/// If one of implemented interfaces is generic instance so all types used in generic are presented in this set. /// If one of implemented interfaces is generic instance so all types used in generic are presented in this set.
/// </summary> /// </summary>
public ISet<Type> GenericImplementedInterfacesTypes { get; set; } public ISet<Type> GenericImplementedInterfacesTypes { get; private set; }
public Type() public Type()
{ {
@ -302,5 +315,7 @@ namespace ICSharpCode.CodeQualityAnalysis
return builder.ToString(); return builder.ToString();
} }
public BitmapSource Icon { get { return NodeIconService.GetIcon(this); } }
} }
} }

Loading…
Cancel
Save