Browse Source

Add Code Analysis AddIn (can control which FxCop rules to run).

For some reason, FxCop is not being run inside SharpDevelop; but it is when running msbuild.exe from the command line.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1192 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
d345513b3b
  1. 20
      src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin
  2. 77
      src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj
  3. 6
      src/AddIns/Misc/CodeAnalysis/CodeAnalysis.sln
  4. 21
      src/AddIns/Misc/CodeAnalysis/Configuration/AssemblyInfo.cs
  5. 153
      src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs
  6. 343
      src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs
  7. 126
      src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.resx
  8. 40
      src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs
  9. 112
      src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs
  10. 203
      src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs
  11. 1
      src/Main/Core/Project/ICSharpCode.Core.csproj
  12. 51
      src/Main/Core/Project/Src/Util/AppDomainLaunchHelper.cs
  13. 9
      src/SharpDevelop.sln

20
src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
<AddIn name = "CodeAnalysis"
author = "Daniel Grunwald"
copyright = "prj:///doc/copyright.txt"
description = "Integrates FxCop code analysis">
<Manifest>
<Identity name = "ICSharpCode.CodeAnalysis"/>
</Manifest>
<Runtime>
<Import assembly = "CodeAnalysis.dll"/>
</Runtime>
<Path path = "/SharpDevelop/BackendBindings/ProjectOptions/C#">
<DialogPanel id = "CodeAnalysis"
label = "${res:ICSharpCode.CodeAnalysis}"
insertafter = "Publish"
class = "ICSharpCode.CodeAnalysis.AnalysisProjectOptionsPanel"/>
</Path>
</AddIn>

77
src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>ICSharpCode.CodeAnalysis</RootNamespace>
<AssemblyName>CodeAnalysis</AssemblyName>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{3EAA45A9-735C-4AC7-A799-947B93EA449D}</ProjectGuid>
<OutputPath>..\..\..\..\AddIns\AddIns\Misc\CodeAnalysis\</OutputPath>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<PlatformTarget>AnyCPU</PlatformTarget>
<FileAlignment>4096</FileAlignment>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
<IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
<Optimize>False</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
<IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
<Optimize>True</Optimize>
<DefineConstants>TRACE</DefineConstants>
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<None Include="CodeAnalysis.addin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Configuration\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Src\AnalysisProjectOptionsPanel.cs" />
<Compile Include="Src\AnalysisProjectOptions.Designer.cs">
<DependentUpon>AnalysisProjectOptions.cs</DependentUpon>
</Compile>
<Compile Include="Src\AnalysisProjectOptions.cs" />
<EmbeddedResource Include="Src\AnalysisProjectOptions.resx">
<DependentUpon>AnalysisProjectOptions.cs</DependentUpon>
</EmbeddedResource>
<Compile Include="Src\FxCopWrapper.cs" />
<Compile Include="Src\FxCopRule.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj">
<Project>{2748AD25-9C63-4E12-877B-4DCE96FBED54}</Project>
<Name>ICSharpCode.SharpDevelop</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Main\Core\Project\ICSharpCode.Core.csproj">
<Project>{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}</Project>
<Name>ICSharpCode.Core</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

6
src/AddIns/Misc/CodeAnalysis/CodeAnalysis.sln

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# SharpDevelop 2.1.0.1190
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysis", "CodeAnalysis.csproj", "{3EAA45A9-735C-4AC7-A799-947B93EA449D}"
EndProject
Global
EndGlobal

21
src/AddIns/Misc/CodeAnalysis/Configuration/AssemblyInfo.cs

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following
// attributes.
//
// change them to the information which is associated with the assembly
// you compile.
[assembly: AssemblyTitle("CodeAnalysis")]
[assembly: AssemblyDescription("AddIn for SharpDevelop 2.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

153
src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs generated

@ -0,0 +1,153 @@ @@ -0,0 +1,153 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: ${DATE}
* Time: ${TIME}
*/
namespace ICSharpCode.CodeAnalysis
{
partial class AnalysisProjectOptions : System.Windows.Forms.UserControl
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the control.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.SplitContainer splitContainer1;
System.Windows.Forms.Panel panel1;
this.ruleLabel = new System.Windows.Forms.Label();
this.warningOrErrorLabel = new System.Windows.Forms.Label();
this.enableCheckBox = new System.Windows.Forms.CheckBox();
this.ruleTreeView = new System.Windows.Forms.TreeView();
splitContainer1 = new System.Windows.Forms.SplitContainer();
panel1 = new System.Windows.Forms.Panel();
splitContainer1.Panel1.SuspendLayout();
splitContainer1.Panel2.SuspendLayout();
splitContainer1.SuspendLayout();
panel1.SuspendLayout();
this.SuspendLayout();
//
// splitContainer1
//
splitContainer1.BackColor = System.Drawing.SystemColors.ControlDark;
splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
splitContainer1.Location = new System.Drawing.Point(1, 1);
splitContainer1.Name = "splitContainer1";
//
// splitContainer1.Panel1
//
splitContainer1.Panel1.Controls.Add(this.ruleLabel);
splitContainer1.Panel1.RightToLeft = System.Windows.Forms.RightToLeft.No;
//
// splitContainer1.Panel2
//
splitContainer1.Panel2.Controls.Add(this.warningOrErrorLabel);
splitContainer1.Panel2.RightToLeft = System.Windows.Forms.RightToLeft.No;
splitContainer1.RightToLeft = System.Windows.Forms.RightToLeft.No;
splitContainer1.Size = new System.Drawing.Size(375, 17);
splitContainer1.SplitterDistance = 208;
splitContainer1.SplitterWidth = 2;
splitContainer1.TabIndex = 1;
//
// ruleLabel
//
this.ruleLabel.BackColor = System.Drawing.SystemColors.ControlLight;
this.ruleLabel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ruleLabel.Location = new System.Drawing.Point(0, 0);
this.ruleLabel.Name = "ruleLabel";
this.ruleLabel.Size = new System.Drawing.Size(208, 17);
this.ruleLabel.TabIndex = 0;
this.ruleLabel.Text = "${res:ICSharpCode.CodeAnalysis.Rule}";
//
// warningOrErrorLabel
//
this.warningOrErrorLabel.BackColor = System.Drawing.SystemColors.ControlLight;
this.warningOrErrorLabel.Dock = System.Windows.Forms.DockStyle.Fill;
this.warningOrErrorLabel.Location = new System.Drawing.Point(0, 0);
this.warningOrErrorLabel.Name = "warningOrErrorLabel";
this.warningOrErrorLabel.Size = new System.Drawing.Size(165, 17);
this.warningOrErrorLabel.TabIndex = 0;
this.warningOrErrorLabel.Text = "${res:ICSharpCode.CodeAnalysis.ProjectOptions.WarningOrError}";
//
// panel1
//
panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
panel1.BackColor = System.Drawing.SystemColors.InactiveCaption;
panel1.Controls.Add(splitContainer1);
panel1.Location = new System.Drawing.Point(15, 33);
panel1.Name = "panel1";
panel1.Padding = new System.Windows.Forms.Padding(1);
panel1.Size = new System.Drawing.Size(377, 19);
panel1.TabIndex = 3;
//
// enableCheckBox
//
this.enableCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.enableCheckBox.Location = new System.Drawing.Point(15, 4);
this.enableCheckBox.Name = "enableCheckBox";
this.enableCheckBox.Size = new System.Drawing.Size(376, 24);
this.enableCheckBox.TabIndex = 0;
this.enableCheckBox.Text = "${res:ICSharpCode.CodeAnalysis.ProjectOptions.Enable}";
this.enableCheckBox.UseVisualStyleBackColor = true;
//
// ruleTreeView
//
this.ruleTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ruleTreeView.CheckBoxes = true;
this.ruleTreeView.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawText;
this.ruleTreeView.Location = new System.Drawing.Point(15, 51);
this.ruleTreeView.Name = "ruleTreeView";
this.ruleTreeView.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.ruleTreeView.Size = new System.Drawing.Size(377, 190);
this.ruleTreeView.TabIndex = 2;
this.ruleTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.RuleTreeViewAfterCheck);
this.ruleTreeView.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.RuleTreeViewDrawNode);
this.ruleTreeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.RuleTreeViewMouseDown);
//
// AnalysisProjectOptions
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.ruleTreeView);
this.Controls.Add(this.enableCheckBox);
this.Controls.Add(panel1);
this.Name = "AnalysisProjectOptions";
this.Size = new System.Drawing.Size(395, 244);
splitContainer1.Panel1.ResumeLayout(false);
splitContainer1.Panel2.ResumeLayout(false);
splitContainer1.ResumeLayout(false);
panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
private System.Windows.Forms.Label warningOrErrorLabel;
private System.Windows.Forms.TreeView ruleTreeView;
private System.Windows.Forms.Label ruleLabel;
private System.Windows.Forms.CheckBox enableCheckBox;
}
}

343
src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs

@ -0,0 +1,343 @@ @@ -0,0 +1,343 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 28.02.2006
* Time: 15:52
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.CodeAnalysis
{
public partial class AnalysisProjectOptions
{
Dictionary<string, RuleTreeNode> rules = new Dictionary<string, RuleTreeNode>();
public AnalysisProjectOptions()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
enableCheckBox.Text = StringParser.Parse(enableCheckBox.Text);
ruleLabel.Text = StringParser.Parse(ruleLabel.Text);
warningOrErrorLabel.Text = StringParser.Parse(warningOrErrorLabel.Text);
ruleLabel.SizeChanged += delegate { ruleTreeView.Invalidate(); };
}
bool initSuccess;
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (ruleTreeView.Nodes.Count == 0 && this.Visible) {
FxCopWrapper.GetRuleList(Callback);
if (ruleTreeView.Nodes.Count == 0) {
ruleTreeView.Nodes.Add(StringParser.Parse("${res:ICSharpCode.CodeAnalysis.ProjectOptions.LoadingRules}"));
}
}
}
void Callback(List<FxCopCategory> ruleList)
{
if (WorkbenchSingleton.InvokeRequired) {
WorkbenchSingleton.SafeThreadAsyncCall((Action<List<FxCopCategory>>)Callback, ruleList);
} else {
ruleTreeView.Nodes.Clear();
if (ruleList == null || ruleList.Count == 0) {
ruleTreeView.Nodes.Add(new TreeNode(StringParser.Parse("${res:ICSharpCode.CodeAnalysis.ProjectOptions.CannotFindFxCop}")));
ruleTreeView.Nodes.Add(new TreeNode(StringParser.Parse("${res:ICSharpCode.CodeAnalysis.ProjectOptions.SpecifyFxCopPath}")));
} else {
foreach (FxCopCategory cat in ruleList) {
CategoryTreeNode catNode = new CategoryTreeNode(cat);
ruleTreeView.Nodes.Add(catNode);
foreach (RuleTreeNode ruleNode in catNode.Nodes) {
rules.Add(ruleNode.Identifier, ruleNode);
}
}
initSuccess = true;
ReadRuleString();
}
}
}
#region TreeView drawing
class CategoryTreeNode : TreeNode
{
internal FxCopCategory category;
public CategoryTreeNode(FxCopCategory category)
{
this.category = category;
this.Text = category.DisplayName;
foreach (FxCopRule rule in category.Rules) {
this.Nodes.Add(new RuleTreeNode(rule));
}
}
internal int ErrorState {
get {
bool allWarn = true;
bool allErr = true;
foreach (RuleTreeNode tn in Nodes) {
if (tn.isError)
allWarn = false;
else
allErr = false;
}
if (allErr)
return 1;
else if (allWarn)
return 0;
else
return -1;
}
}
}
class RuleTreeNode : TreeNode
{
internal FxCopRule rule;
internal bool isError;
public RuleTreeNode(FxCopRule rule)
{
this.rule = rule;
this.Text = rule.DisplayName;
}
public string Identifier {
get {
return rule.CategoryName + "#" + rule.CheckId;
}
}
}
void RuleTreeViewDrawNode(object sender, DrawTreeNodeEventArgs e)
{
if (e.Bounds.X < 5) return;
int state;
if (e.Node is CategoryTreeNode) {
state = (e.Node as CategoryTreeNode).ErrorState;
} else if (e.Node is RuleTreeNode) {
state = (e.Node as RuleTreeNode).isError ? 1 : 0;
} else {
e.DrawDefault = true;
return;
}
e.DrawDefault = false;
if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected) {
e.Graphics.DrawString(e.Node.Text, ruleTreeView.Font, SystemBrushes.HighlightText, e.Bounds.Location);
} else {
e.Graphics.DrawString(e.Node.Text, ruleTreeView.Font, SystemBrushes.WindowText, e.Bounds.Location);
}
e.Graphics.DrawLine(SystemPens.WindowFrame, ruleLabel.Width, e.Bounds.Top, ruleLabel.Width, e.Bounds.Bottom);
if (state == 0) {
// Warning
e.Graphics.DrawIcon(SystemIcons.Warning, new Rectangle(ruleLabel.Width + 4, e.Bounds.Y, 16, 16));
e.Graphics.DrawString(ResourceService.GetString("Global.WarningText"), ruleTreeView.Font, SystemBrushes.WindowText, ruleLabel.Width + 24, e.Bounds.Y);
} else if (state == 1) {
// Error
e.Graphics.DrawIcon(SystemIcons.Error, new Rectangle(ruleLabel.Width + 4, e.Bounds.Y, 16, 16));
e.Graphics.DrawString(ResourceService.GetString("Global.ErrorText"), ruleTreeView.Font, SystemBrushes.WindowText, ruleLabel.Width + 24, e.Bounds.Y);
} else {
// Mixed
e.Graphics.DrawString(StringParser.Parse("${res:ICSharpCode.CodeAnalysis.ProjectOptions.WarningErrorMixed}"),
ruleTreeView.Font, SystemBrushes.WindowText, ruleLabel.Width + 24, e.Bounds.Y);
}
}
#endregion
#region Rule String Property
string CreateRuleString()
{
StringBuilder b = new StringBuilder();
foreach (TreeNode category in ruleTreeView.Nodes) {
foreach (RuleTreeNode rule in category.Nodes) {
if (!rule.Checked || rule.isError) {
if (b.Length > 0)
b.Append(';');
if (rule.Checked)
b.Append('+');
else
b.Append('-');
if (rule.isError)
b.Append('!');
b.Append(rule.Identifier);
}
}
}
return b.ToString();
}
void ReadRuleString()
{
userCheck = false;
foreach (TreeNode cat in ruleTreeView.Nodes) {
foreach (RuleTreeNode rtn in cat.Nodes) {
rtn.Checked = true;
rtn.isError = false;
}
}
foreach (string rule2 in ruleString.Split(';')) {
string rule = rule2;
if (rule.Length == 0) continue;
bool active = true;
bool error = false;
if (rule.StartsWith("-")) {
active = false;
rule = rule.Substring(1);
} else if (rule.StartsWith("+")) {
rule = rule.Substring(1);
}
if (rule.StartsWith("!")) {
error = true;
rule = rule.Substring(1);
}
RuleTreeNode ruleNode;
if (rules.TryGetValue(rule, out ruleNode)) {
ruleNode.Checked = active;
ruleNode.isError = error;
}
}
foreach (TreeNode cat in ruleTreeView.Nodes) {
bool noneChecked = true;
foreach (RuleTreeNode rtn in cat.Nodes) {
if (rtn.Checked) {
noneChecked = false;
break;
}
}
cat.Checked = !noneChecked;
}
ruleTreeView.Invalidate();
userCheck = true;
}
string ruleString = "";
public string RuleString {
get {
if (initSuccess)
return CreateRuleString();
else
return ruleString;
}
set {
ruleString = value;
if (initSuccess) {
ReadRuleString();
}
}
}
#endregion
#region ConfigurationGuiBinding
public CheckBox EnableCheckBox {
get {
return enableCheckBox;
}
}
public ConfigurationGuiBinding CreateBinding()
{
return new ConfigBinding(this);
}
class ConfigBinding : ConfigurationGuiBinding
{
readonly AnalysisProjectOptions po;
public ConfigBinding(AnalysisProjectOptions po)
{
this.po = po;
po.OptionChanged += delegate {
Helper.IsDirty = true;
};
}
public override void Load()
{
po.RuleString = Get("");
}
public override bool Save()
{
Set(po.RuleString);
return true;
}
}
#endregion
public event EventHandler OptionChanged;
protected virtual void OnOptionChanged(EventArgs e)
{
if (OptionChanged != null) {
OptionChanged(this, e);
}
}
void RuleTreeViewMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && e.X > ruleLabel.Width) {
TreeNode node = ruleTreeView.GetNodeAt(20, e.Y);
if (node != null) {
if (node is RuleTreeNode) {
((RuleTreeNode)node).isError = !((RuleTreeNode)node).isError;
} else if (node is CategoryTreeNode) {
if ((node as CategoryTreeNode).ErrorState == 0) {
foreach (RuleTreeNode rtn in node.Nodes) {
rtn.isError = true;
}
} else {
foreach (RuleTreeNode rtn in node.Nodes) {
rtn.isError = false;
}
}
}
ruleTreeView.Invalidate();
OnOptionChanged(EventArgs.Empty);
}
}
}
bool userCheck;
void RuleTreeViewAfterCheck(object sender, TreeViewEventArgs e)
{
if (userCheck) {
if (e.Node is CategoryTreeNode) {
userCheck = false;
foreach (TreeNode subNode in e.Node.Nodes) {
subNode.Checked = e.Node.Checked;
}
userCheck = true;
} else if (e.Node is RuleTreeNode) {
userCheck = false;
bool anyChecked = false;
foreach (TreeNode sibling in e.Node.Parent.Nodes) {
if (sibling.Checked)
anyChecked = true;
}
e.Node.Parent.Checked = anyChecked;
userCheck = true;
}
OnOptionChanged(EventArgs.Empty);
}
}
}
}

126
src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.resx

@ -0,0 +1,126 @@ @@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="splitContainer1.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="panel1.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

40
src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 28.02.2006
* Time: 15:29
*/
using System;
using System.Drawing;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.CodeAnalysis
{
public class AnalysisProjectOptionsPanel : AbstractProjectOptionPanel
{
public override void LoadPanelContents()
{
InitializeHelper();
AnalysisProjectOptions po = new AnalysisProjectOptions();
po.Dock = DockStyle.Fill;
Controls.Add(po);
ChooseStorageLocationButton btn;
btn = helper.BindBoolean(po.EnableCheckBox, "RunCodeAnalysis", false).CreateLocationButton(po.EnableCheckBox);
ConfigurationGuiBinding binding = po.CreateBinding();
binding.RegisterLocationButton(btn);
helper.AddBinding("CodeAnalysisRules", binding);
Control ctl = helper.CreateConfigurationSelector();
ctl.Dock = DockStyle.Top;
Controls.Add(ctl);
}
}
}

112
src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs

@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 28.02.2006
* Time: 17:16
*/
using System;
using System.Collections.Generic;
namespace ICSharpCode.CodeAnalysis
{
public class FxCopRule : IComparable
{
readonly string checkId;
readonly string displayName;
readonly string categoryName;
readonly string description;
readonly string url;
public FxCopRule(string checkId, string displayName, string categoryName, string description, string url)
{
this.checkId = checkId;
this.displayName = displayName;
this.categoryName = categoryName;
this.description = description;
this.url = url;
}
public string CheckId {
get {
return checkId;
}
}
public string DisplayName {
get {
return displayName;
}
}
public string CategoryName {
get {
return categoryName;
}
}
public string Description {
get {
return description;
}
}
public string Url {
get {
return url;
}
}
public override string ToString()
{
return string.Format("[FxCopRule {0}#{1}]", this.categoryName, this.checkId);
}
public int CompareTo(object obj)
{
FxCopRule o = (FxCopRule)obj;
int r = categoryName.CompareTo(o.categoryName);
if (r != 0) return r;
return displayName.CompareTo(o.displayName);
}
}
public class FxCopCategory
{
readonly string name;
readonly string displayName;
readonly List<FxCopRule> rules = new List<FxCopRule>();
public FxCopCategory(string name)
{
this.name = name;
if (name.StartsWith("Microsoft."))
displayName = name.Substring(10);
else
displayName = name;
}
public string Name {
get {
return name;
}
}
public string DisplayName {
get {
return displayName;
}
}
public List<FxCopRule> Rules {
get {
return rules;
}
}
public override string ToString()
{
return string.Format("[FxCopCategory {0}]", this.name);
}
}
}

203
src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs

@ -0,0 +1,203 @@ @@ -0,0 +1,203 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 28.02.2006
* Time: 16:24
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.Win32;
using ICSharpCode.Core;
namespace ICSharpCode.CodeAnalysis
{
public static class FxCopWrapper
{
static List<FxCopCategory> rules = new List<FxCopCategory>();
static List<Action<List<FxCopCategory>>> callbacks = new List<Action<List<FxCopCategory>>>();
/// <summary>
/// Gets the rules supported by the current FxCop version. The rules are loaded on a separate
/// thread, the callback is fired when the action has completed.
/// Warning: the callback might be fired on the current thread if the rules are already loaded,
/// or on another thread!
/// </summary>
public static void GetRuleList(Action<List<FxCopCategory>> callback)
{
int count;
lock (rules) {
count = rules.Count;
if (count == 0) {
callbacks.Add(callback);
if (callbacks.Count == 1) {
// Start the thread:
System.Threading.ThreadPool.QueueUserWorkItem(RunGetRuleList);
}
}
}
if (count > 0) {
callback(rules);
}
}
public static string FindFxCopPath()
{
string fxCopPath = PropertyService.Get("CodeAnalysis.FxCopPath");
if (fxCopPath.Length > 0 && File.Exists(Path.Combine(fxCopPath, "FxCopCommon.dll"))) {
return fxCopPath;
}
fxCopPath = FromRegistry(Registry.CurrentUser.OpenSubKey(@"Software\Classes\FxCopProject\Shell\Open\Command"));
if (fxCopPath.Length > 0 && File.Exists(Path.Combine(fxCopPath, "FxCopCommon.dll"))) {
return fxCopPath;
}
fxCopPath = FromRegistry(Registry.ClassesRoot.OpenSubKey(@"FxCopProject\Shell\Open\Command"));
if (fxCopPath.Length > 0 && File.Exists(Path.Combine(fxCopPath, "FxCopCommon.dll"))) {
return fxCopPath;
}
return null;
}
static string FromRegistry(RegistryKey key)
{
if (key == null) return string.Empty;
using (key) {
string cmd = key.GetValue("").ToString();
int pos;
if (cmd.StartsWith("\""))
pos = cmd.IndexOf('"', 1);
else
pos = cmd.IndexOf(' ');
try {
if (cmd.StartsWith("\""))
return Path.GetDirectoryName(cmd.Substring(1, pos - 1));
else
return Path.GetDirectoryName(cmd.Substring(0, pos));
} catch (ArgumentException ex) {
LoggingService.Warn(cmd);
LoggingService.Warn(ex);
return string.Empty;
}
}
}
static void RunGetRuleList(object state)
{
LoggingService.Debug("Trying to find FxCop rules");
string fxCopPath = FindFxCopPath();
if (fxCopPath != null) {
try {
GetRuleListAndSort(fxCopPath);
} catch (Exception ex) {
LoggingService.Warn(ex);
}
}
Action<List<FxCopCategory>>[] callbacks_tmp;
lock (rules) {
callbacks_tmp = callbacks.ToArray();
callbacks.Clear();
}
LoggingService.Debug("Finished getting FxCop rules, invoking " + callbacks_tmp.Length + " callback");
foreach (Action<List<FxCopCategory>> callback in callbacks_tmp) {
callback(rules);
}
}
static void GetRuleListAndSort(string fxCopPath)
{
AppDomainSetup setup = new AppDomainSetup();
setup.DisallowCodeDownload = true;
setup.ApplicationBase = fxCopPath;
AppDomain domain = AppDomain.CreateDomain("FxCop Rule Loading Domain", AppDomain.CurrentDomain.Evidence, setup);
string[][] ruleTextList;
try {
ruleTextList = (string[][])AppDomainLaunchHelper.LaunchInAppDomain(domain, typeof(FxCopWrapper), "GetRuleListInCurrentAppDomain", fxCopPath);
} finally {
AppDomain.Unload(domain);
}
FxCopRule[] ruleList = new FxCopRule[ruleTextList.Length];
for (int i = 0; i < ruleTextList.Length; i++) {
ruleList[i] = new FxCopRule(ruleTextList[i][0], ruleTextList[i][1],
ruleTextList[i][2], ruleTextList[i][3],
ruleTextList[i][4]);
}
Array.Sort(ruleList);
lock (rules) {
FxCopCategory cat = null;
foreach (FxCopRule rule in ruleList) {
if (cat == null || cat.Name != rule.CategoryName) {
cat = new FxCopCategory(rule.CategoryName);
rules.Add(cat);
}
cat.Rules.Add(rule);
}
}
}
// We don't want to reference the FxCop assembly
static object CallMethod(object instance, string name, params object[] args)
{
return instance.GetType().InvokeMember(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, instance, args);
}
static object CallMethod(Type type, string name, BindingFlags flags, object instance, params object[] args)
{
return type.InvokeMember(name, flags | BindingFlags.Public | BindingFlags.InvokeMethod,
null, instance, args);
}
static object GetProp(object instance, string name)
{
return instance.GetType().InvokeMember(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
null, instance, null);
}
static string GetSProp(object instance, string name)
{
object v = GetProp(instance, name);
if (v == null)
return string.Empty;
else
return v.ToString();
}
public static string[][] GetRuleListInCurrentAppDomain(string fxCopPath)
{
Assembly asm = Assembly.LoadFrom(Path.Combine(fxCopPath, "FxCopCommon.dll"));
Type fxCopOM = asm.GetType("Microsoft.FxCop.Common.FxCopOM");
CallMethod(fxCopOM, "Initialize", BindingFlags.Static, null);
object project = asm.CreateInstance("Microsoft.FxCop.Common.Project");
fxCopOM.InvokeMember("Project", BindingFlags.Public | BindingFlags.Static | BindingFlags.SetProperty,
null, null, new object[] { project });
object exceptionList = CallMethod(project, "Initialize");
foreach (Exception ex in ((IEnumerable)exceptionList)) {
LoggingService.Warn(ex);
}
IEnumerable ruleList = (IEnumerable)GetProp(GetProp(project, "AllRules"), "Values");
List<string[]> rules = new List<string[]>();
foreach (object ruleContainer in ruleList) {
object rule = GetProp(ruleContainer, "IRule");
rules.Add(new string[] {
GetSProp(rule, "CheckId"),
GetSProp(rule, "Name"),
GetSProp(rule, "Category"),
GetSProp(rule, "Description"),
GetSProp(rule, "Url")
});
}
return rules.ToArray();
}
}
}

1
src/Main/Core/Project/ICSharpCode.Core.csproj

@ -148,6 +148,7 @@ @@ -148,6 +148,7 @@
<Compile Include="..\..\GlobalAssemblyInfo.cs">
<Link>Configuration\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Src\Util\AppDomainLaunchHelper.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Src\Services\LoggingService" />

51
src/Main/Core/Project/Src/Util/AppDomainLaunchHelper.cs

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 28.02.2006
* Time: 18:03
*/
using System;
using System.Reflection;
namespace ICSharpCode.Core
{
/// <summary>
/// Because AddIn assemblies are loaded into the LoadFrom context, creating AppDomains in them that
/// use an arbitrary ApplicationBase path does not work correctly.
/// This class contains a static method that helps launching a static method on a type in a new AppDomain.
/// </summary>
/// <example>
/// <code>
/// public static class CurrentClass { // is NOT MarshalByRef
/// public static ResultClass[] GetResults()
/// {
/// AppDomainSetup setup = new AppDomainSetup();
/// setup.ApplicationBase = myApplicationBase;
/// AppDomain domain = AppDomain.CreateDomain("Display name for domain", AppDomain.CurrentDomain.Evidence, setup);
/// try {
/// return (ResultClass[])AppDomainLaunchHelper.LaunchInAppDomain(domain, typeof(CurrentClass), "GetResultsDirectly", requestObject);
/// } finally {
/// AppDomain.Unload(domain);
/// }
/// }
/// public static ResultClass[] GetResultsDirectly(Request requestObject) { ... }
/// }
/// [Serializable] class Request { ... } // must be serializable !!!
/// [Serializable] class ResultClass { ... } // must be serializable !!!
/// </code></example>
public class AppDomainLaunchHelper : MarshalByRefObject
{
public object LaunchMethod(string assemblyFile, string typeName, string methodName, object[] arguments)
{
Type t = Assembly.LoadFrom(assemblyFile).GetType(typeName);
return t.InvokeMember(methodName, (BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod), null, null, arguments);
}
public static object LaunchInAppDomain(AppDomain domain, Type type, string methodName, params object[] arguments)
{
AppDomainLaunchHelper h = (AppDomainLaunchHelper)domain.CreateInstanceFromAndUnwrap(typeof(AppDomainLaunchHelper).Assembly.Location, typeof(AppDomainLaunchHelper).FullName);
return h.LaunchMethod(type.Assembly.Location, type.FullName, methodName, arguments);
}
}
}

9
src/SharpDevelop.sln

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# SharpDevelop 2.0.0.1128
# SharpDevelop 2.1.0.1190
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{14A277EE-7DF1-4529-B639-7D1EF334C1C5}"
ProjectSection(SolutionItems) = postProject
EndProjectSection
@ -46,6 +46,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{CE5B42B7-6 @@ -46,6 +46,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{CE5B42B7-6
ProjectSection(SolutionItems) = postProject
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysis", "AddIns\Misc\CodeAnalysis\CodeAnalysis.csproj", "{3EAA45A9-735C-4AC7-A799-947B93EA449D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SubversionAddIn", "AddIns\Misc\SubversionAddIn\Project\SubversionAddIn.csproj", "{17F4D7E0-6933-4C2E-8714-FD7E98D625D5}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "HtmlHelp2JScriptGlobals", "AddIns\Misc\HtmlHelp2\JScriptGlobals\HtmlHelp2JScriptGlobals.vbproj", "{E54A5AD2-418D-4A85-BA5E-CD803DE38715}"
@ -282,6 +284,10 @@ Global @@ -282,6 +284,10 @@ Global
{17F4D7E0-6933-4C2E-8714-FD7E98D625D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{17F4D7E0-6933-4C2E-8714-FD7E98D625D5}.Release|Any CPU.Build.0 = Release|Any CPU
{17F4D7E0-6933-4C2E-8714-FD7E98D625D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3EAA45A9-735C-4AC7-A799-947B93EA449D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3EAA45A9-735C-4AC7-A799-947B93EA449D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3EAA45A9-735C-4AC7-A799-947B93EA449D}.Release|Any CPU.Build.0 = Release|Any CPU
{3EAA45A9-735C-4AC7-A799-947B93EA449D}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5}
@ -318,6 +324,7 @@ Global @@ -318,6 +324,7 @@ Global
{1F261725-6318-4434-A1B1-6C70CE4CD324} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2}
{E54A5AD2-418D-4A85-BA5E-CD803DE38715} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2}
{17F4D7E0-6933-4C2E-8714-FD7E98D625D5} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2}
{3EAA45A9-735C-4AC7-A799-947B93EA449D} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2}
{B08385CD-F0CC-488C-B4F4-EEB34B6D2688} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D}
{1D18D788-F7EE-4585-A23B-34DC8EC63CB8} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D}
{EC06F96A-AEEC-49D6-B03D-AB87C6EB674C} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D}

Loading…
Cancel
Save