diff --git a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin
new file mode 100644
index 0000000000..8ad4057baa
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj
new file mode 100644
index 0000000000..d264f6dda3
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj
@@ -0,0 +1,77 @@
+
+
+ Library
+ ICSharpCode.CodeAnalysis
+ CodeAnalysis
+ Debug
+ AnyCPU
+ {3EAA45A9-735C-4AC7-A799-947B93EA449D}
+ ..\..\..\..\AddIns\AddIns\Misc\CodeAnalysis\
+ False
+ False
+ False
+ Auto
+ 4194304
+ AnyCPU
+ 4096
+ 4
+ false
+
+
+ obj\
+ obj\Debug\
+ False
+ DEBUG;TRACE
+ true
+ Full
+ True
+
+
+ obj\
+ obj\Release\
+ True
+ TRACE
+ False
+ None
+ False
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+ Configuration\GlobalAssemblyInfo.cs
+
+
+
+ AnalysisProjectOptions.cs
+
+
+
+ AnalysisProjectOptions.cs
+
+
+
+
+
+
+ {2748AD25-9C63-4E12-877B-4DCE96FBED54}
+ ICSharpCode.SharpDevelop
+ False
+
+
+ {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}
+ ICSharpCode.Core
+ False
+
+
+
+
\ No newline at end of file
diff --git a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.sln b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.sln
new file mode 100644
index 0000000000..9ace730fd7
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.sln
@@ -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
diff --git a/src/AddIns/Misc/CodeAnalysis/Configuration/AssemblyInfo.cs b/src/AddIns/Misc/CodeAnalysis/Configuration/AssemblyInfo.cs
new file mode 100644
index 0000000000..d29eaefb2f
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/Configuration/AssemblyInfo.cs
@@ -0,0 +1,21 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+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("")]
diff --git a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs
new file mode 100644
index 0000000000..364dfbca4e
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs
@@ -0,0 +1,153 @@
+/*
+ * Created by SharpDevelop.
+ * User: Daniel Grunwald
+ * Date: ${DATE}
+ * Time: ${TIME}
+ */
+namespace ICSharpCode.CodeAnalysis
+{
+ partial class AnalysisProjectOptions : System.Windows.Forms.UserControl
+ {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Disposes resources used by the control.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// 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.
+ ///
+ 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;
+ }
+}
diff --git a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs
new file mode 100644
index 0000000000..f1cfa0e0f4
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs
@@ -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 rules = new Dictionary();
+
+ 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 ruleList)
+ {
+ if (WorkbenchSingleton.InvokeRequired) {
+ WorkbenchSingleton.SafeThreadAsyncCall((Action>)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);
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.resx b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.resx
new file mode 100644
index 0000000000..a98b238dd9
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+ False
+
+
\ No newline at end of file
diff --git a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs
new file mode 100644
index 0000000000..83e65765e5
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs
@@ -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);
+ }
+ }
+}
diff --git a/src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs b/src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs
new file mode 100644
index 0000000000..c94661329d
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs
@@ -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 rules = new List();
+
+ 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 Rules {
+ get {
+ return rules;
+ }
+ }
+
+ public override string ToString()
+ {
+ return string.Format("[FxCopCategory {0}]", this.name);
+ }
+ }
+}
diff --git a/src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs b/src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs
new file mode 100644
index 0000000000..23104bf69e
--- /dev/null
+++ b/src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs
@@ -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 rules = new List();
+ static List>> callbacks = new List>>();
+
+ ///
+ /// 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!
+ ///
+ public static void GetRuleList(Action> 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>[] callbacks_tmp;
+ lock (rules) {
+ callbacks_tmp = callbacks.ToArray();
+ callbacks.Clear();
+ }
+ LoggingService.Debug("Finished getting FxCop rules, invoking " + callbacks_tmp.Length + " callback");
+ foreach (Action> 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 rules = new List();
+ 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();
+ }
+ }
+}
diff --git a/src/Main/Core/Project/ICSharpCode.Core.csproj b/src/Main/Core/Project/ICSharpCode.Core.csproj
index 866780f348..827e69892e 100644
--- a/src/Main/Core/Project/ICSharpCode.Core.csproj
+++ b/src/Main/Core/Project/ICSharpCode.Core.csproj
@@ -148,6 +148,7 @@
Configuration\GlobalAssemblyInfo.cs
+
diff --git a/src/Main/Core/Project/Src/Util/AppDomainLaunchHelper.cs b/src/Main/Core/Project/Src/Util/AppDomainLaunchHelper.cs
new file mode 100644
index 0000000000..c85f8a6b0d
--- /dev/null
+++ b/src/Main/Core/Project/Src/Util/AppDomainLaunchHelper.cs
@@ -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
+{
+ ///
+ /// 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.
+ ///
+ ///
+ ///
+ /// 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 !!!
+ ///
+ 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);
+ }
+ }
+}
diff --git a/src/SharpDevelop.sln b/src/SharpDevelop.sln
index 6b566a102c..e4dd9694b1 100644
--- a/src/SharpDevelop.sln
+++ b/src/SharpDevelop.sln
@@ -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
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
{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
{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}