From 05c43ceb3f03f1386cf7f42bc7e89efc85cae1e9 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 22 Mar 2006 08:46:10 +0000 Subject: [PATCH] Worked on FxCop integration. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1233 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Boo/BooBinding/Project/BooBinding.addin | 1 + .../CSharpBinding/Project/CSharpBinding.addin | 1 + .../ILAsmBinding/Project/ILAsmBinding.addin | 1 + .../VBNetBinding/Project/VBNetBinding.addin | 1 + .../Misc/CodeAnalysis/CodeAnalysis.addin | 10 +- .../Misc/CodeAnalysis/CodeAnalysis.csproj | 1 + .../Src/AnalysisProjectOptions.Designer.cs | 43 ++++-- .../Src/AnalysisProjectOptions.cs | 127 ++++++++++++++++-- .../Src/AnalysisProjectOptionsPanel.cs | 12 +- .../Src/CheckCurrentProjectCommand.cs | 26 ++++ src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs | 21 ++- .../Misc/CodeAnalysis/Src/FxCopWrapper.cs | 102 +++++++++----- .../CodeCoverage/Project/CodeCoverage.addin | 3 +- .../ICSharpCode.Build.Tasks/Project/FxCop.cs | 20 ++- .../Project/SharpDevelop.CodeAnalysis.targets | 2 +- .../Project/Src/Commands/BuildCommands.cs | 19 ++- .../Src/Gui/Components/StringListEditor.cs | 14 ++ .../Project/Src/Project/AbstractProject.cs | 8 +- src/Main/Base/Project/Src/Project/IProject.cs | 8 +- .../Base/Project/Src/Project/MSBuildEngine.cs | 2 +- .../Project/Src/Project/MSBuildProject.cs | 27 ++-- .../Project/Src/Project/Solution/Solution.cs | 12 +- .../ParserService/DefaultProjectContent.cs | 2 +- src/Main/GlobalAssemblyInfo.template | 2 +- 24 files changed, 347 insertions(+), 118 deletions(-) create mode 100644 src/AddIns/Misc/CodeAnalysis/Src/CheckCurrentProjectCommand.cs diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin index 8d2a0e9ae4..b01e9fb297 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin @@ -122,6 +122,7 @@ + diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin index 63b2ccb115..bc5b9ca4ee 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin @@ -70,6 +70,7 @@ + diff --git a/src/AddIns/BackendBindings/ILAsmBinding/Project/ILAsmBinding.addin b/src/AddIns/BackendBindings/ILAsmBinding/Project/ILAsmBinding.addin index c24558fde9..a6a7cd904f 100644 --- a/src/AddIns/BackendBindings/ILAsmBinding/Project/ILAsmBinding.addin +++ b/src/AddIns/BackendBindings/ILAsmBinding/Project/ILAsmBinding.addin @@ -45,6 +45,7 @@ + diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin b/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin index 9361331540..3b7062fc7e 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.addin @@ -75,6 +75,7 @@ + diff --git a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin index 98c410c1cc..2874c6b144 100644 --- a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin +++ b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin @@ -15,10 +15,16 @@ - + + + + + diff --git a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj index d264f6dda3..f04f70b7ff 100644 --- a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj +++ b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj @@ -60,6 +60,7 @@ + diff --git a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs index 364dfbca4e..3d8fe57e17 100644 --- a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs +++ b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.Designer.cs @@ -1,9 +1,10 @@ -/* - * Created by SharpDevelop. - * User: Daniel Grunwald - * Date: ${DATE} - * Time: ${TIME} - */ +// +// +// +// +// $Revision$ +// + namespace ICSharpCode.CodeAnalysis { partial class AnalysisProjectOptions : System.Windows.Forms.UserControl @@ -40,6 +41,7 @@ namespace ICSharpCode.CodeAnalysis this.warningOrErrorLabel = new System.Windows.Forms.Label(); this.enableCheckBox = new System.Windows.Forms.CheckBox(); this.ruleTreeView = new System.Windows.Forms.TreeView(); + this.changeRuleAssembliesButton = new System.Windows.Forms.Button(); splitContainer1 = new System.Windows.Forms.SplitContainer(); panel1 = new System.Windows.Forms.Panel(); splitContainer1.Panel1.SuspendLayout(); @@ -67,7 +69,7 @@ namespace ICSharpCode.CodeAnalysis 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.SplitterDistance = 214; splitContainer1.SplitterWidth = 2; splitContainer1.TabIndex = 1; // @@ -77,7 +79,7 @@ namespace ICSharpCode.CodeAnalysis 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.Size = new System.Drawing.Size(214, 17); this.ruleLabel.TabIndex = 0; this.ruleLabel.Text = "${res:ICSharpCode.CodeAnalysis.Rule}"; // @@ -87,7 +89,7 @@ namespace ICSharpCode.CodeAnalysis 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.Size = new System.Drawing.Size(159, 17); this.warningOrErrorLabel.TabIndex = 0; this.warningOrErrorLabel.Text = "${res:ICSharpCode.CodeAnalysis.ProjectOptions.WarningOrError}"; // @@ -97,7 +99,7 @@ namespace ICSharpCode.CodeAnalysis | System.Windows.Forms.AnchorStyles.Right))); panel1.BackColor = System.Drawing.SystemColors.InactiveCaption; panel1.Controls.Add(splitContainer1); - panel1.Location = new System.Drawing.Point(15, 33); + panel1.Location = new System.Drawing.Point(15, 57); panel1.Name = "panel1"; panel1.Padding = new System.Windows.Forms.Padding(1); panel1.Size = new System.Drawing.Size(377, 19); @@ -111,7 +113,7 @@ namespace ICSharpCode.CodeAnalysis 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.Text = "${res:ICSharpCode.CodeAnalysis.ProjectOptions.RunOnBuild}"; this.enableCheckBox.UseVisualStyleBackColor = true; // // ruleTreeView @@ -121,19 +123,32 @@ namespace ICSharpCode.CodeAnalysis | 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.Location = new System.Drawing.Point(15, 75); this.ruleTreeView.Name = "ruleTreeView"; this.ruleTreeView.RightToLeft = System.Windows.Forms.RightToLeft.No; - this.ruleTreeView.Size = new System.Drawing.Size(377, 190); + this.ruleTreeView.Size = new System.Drawing.Size(377, 166); 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); // + // changeRuleAssembliesButton + // + this.changeRuleAssembliesButton.AutoSize = true; + this.changeRuleAssembliesButton.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.changeRuleAssembliesButton.Location = new System.Drawing.Point(15, 28); + this.changeRuleAssembliesButton.Name = "changeRuleAssembliesButton"; + this.changeRuleAssembliesButton.Size = new System.Drawing.Size(387, 23); + this.changeRuleAssembliesButton.TabIndex = 4; + this.changeRuleAssembliesButton.Text = "${res:ICSharpCode.CodeAnalysis.ProjectOptions.AddRemoveRuleAssembly}"; + this.changeRuleAssembliesButton.UseVisualStyleBackColor = true; + this.changeRuleAssembliesButton.Click += new System.EventHandler(this.ChangeRuleAssembliesButtonClick); + // // AnalysisProjectOptions // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.changeRuleAssembliesButton); this.Controls.Add(this.ruleTreeView); this.Controls.Add(this.enableCheckBox); this.Controls.Add(panel1); @@ -144,7 +159,9 @@ namespace ICSharpCode.CodeAnalysis splitContainer1.ResumeLayout(false); panel1.ResumeLayout(false); this.ResumeLayout(false); + this.PerformLayout(); } + private System.Windows.Forms.Button changeRuleAssembliesButton; private System.Windows.Forms.Label warningOrErrorLabel; private System.Windows.Forms.TreeView ruleTreeView; private System.Windows.Forms.Label ruleLabel; diff --git a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs index f1cfa0e0f4..def891d6dc 100644 --- a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs +++ b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptions.cs @@ -1,15 +1,16 @@ -/* - * Created by SharpDevelop. - * User: Daniel Grunwald - * Date: 28.02.2006 - * Time: 15:52 - */ +// +// +// +// +// $Revision$ +// using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; +using System.Text.RegularExpressions; using System.Windows.Forms; using ICSharpCode.Core; @@ -33,6 +34,7 @@ namespace ICSharpCode.CodeAnalysis enableCheckBox.Text = StringParser.Parse(enableCheckBox.Text); ruleLabel.Text = StringParser.Parse(ruleLabel.Text); warningOrErrorLabel.Text = StringParser.Parse(warningOrErrorLabel.Text); + changeRuleAssembliesButton.Text = StringParser.Parse(changeRuleAssembliesButton.Text); ruleLabel.SizeChanged += delegate { ruleTreeView.Invalidate(); }; } @@ -44,10 +46,16 @@ namespace ICSharpCode.CodeAnalysis 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}")); - } + ReloadRuleList(); + } + } + + void ReloadRuleList() + { + ruleTreeView.Nodes.Clear(); + FxCopWrapper.GetRuleList(GetRuleAssemblyList(true), Callback); + if (ruleTreeView.Nodes.Count == 0) { + ruleTreeView.Nodes.Add(StringParser.Parse("${res:ICSharpCode.CodeAnalysis.ProjectOptions.LoadingRules}")); } } @@ -57,6 +65,7 @@ namespace ICSharpCode.CodeAnalysis WorkbenchSingleton.SafeThreadAsyncCall((Action>)Callback, ruleList); } else { ruleTreeView.Nodes.Clear(); + rules.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}"))); @@ -65,7 +74,7 @@ namespace ICSharpCode.CodeAnalysis CategoryTreeNode catNode = new CategoryTreeNode(cat); ruleTreeView.Nodes.Add(catNode); foreach (RuleTreeNode ruleNode in catNode.Nodes) { - rules.Add(ruleNode.Identifier, ruleNode); + rules[ruleNode.Identifier] = ruleNode; } } initSuccess = true; @@ -116,7 +125,7 @@ namespace ICSharpCode.CodeAnalysis public RuleTreeNode(FxCopRule rule) { this.rule = rule; - this.Text = rule.DisplayName; + this.Text = rule.CheckId + " : " + rule.DisplayName; } public string Identifier { @@ -245,6 +254,30 @@ namespace ICSharpCode.CodeAnalysis } #endregion + #region Rule Assemblies Property + string ruleAssemblies; + const string DefaultRuleAssemblies = @"$(FxCopDir)\rules"; + + public string RuleAssemblies { + get { + return ruleAssemblies; + } + set { + if (string.IsNullOrEmpty(value)) { + value = DefaultRuleAssemblies; + } + if (ruleAssemblies != value) { + ruleAssemblies = value; + + if (initSuccess) { + OnOptionChanged(EventArgs.Empty); + ReloadRuleList(); + } + } + } + } + #endregion + #region ConfigurationGuiBinding public CheckBox EnableCheckBox { get { @@ -272,11 +305,14 @@ namespace ICSharpCode.CodeAnalysis public override void Load() { po.RuleString = Get(""); + PropertyStorageLocations tmp; + po.RuleAssemblies = Helper.GetProperty("CodeAnalysisRuleAssemblies", "", out tmp); } public override bool Save() { Set(po.RuleString); + Helper.SetProperty("CodeAnalysisRuleAssemblies", (po.RuleAssemblies == DefaultRuleAssemblies) ? "" : po.RuleAssemblies, Location); return true; } } @@ -339,5 +375,72 @@ namespace ICSharpCode.CodeAnalysis OnOptionChanged(EventArgs.Empty); } } + + string[] GetRuleAssemblyList(bool replacePath) + { + List list = new List(); + foreach (string dir in ruleAssemblies.Split(';')) { + if (string.Equals(dir, "$(FxCopDir)\\rules", StringComparison.OrdinalIgnoreCase)) + continue; + if (string.Equals(dir, "$(FxCopDir)/rules", StringComparison.OrdinalIgnoreCase)) + continue; + if (replacePath) { + list.Add(Regex.Replace(dir, @"\$\(FxCopDir\)", FxCopWrapper.FindFxCopPath(), RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)); + } else { + list.Add(dir); + } + } + return list.ToArray(); + } + + void ChangeRuleAssembliesButtonClick(object sender, EventArgs e) + { + using (Form frm = new Form()) { + frm.Text = changeRuleAssembliesButton.Text; + + StringListEditor ed = new StringListEditor(); + ed.Dock = DockStyle.Fill; + ed.ManualOrder = false; + ed.BrowseForDirectory = true; + ed.AutoAddAfterBrowse = true; + ed.TitleText = "${res:ICSharpCode.CodeAnalysis.ProjectOptions.ChooseRuleAssemblyDirectory}"; + + ed.LoadList(GetRuleAssemblyList(false)); + FlowLayoutPanel p = new FlowLayoutPanel(); + p.Dock = DockStyle.Bottom; + p.FlowDirection = FlowDirection.RightToLeft; + + Button btn = new Button(); + p.Height = btn.Height + 8; + btn.DialogResult = DialogResult.Cancel; + btn.Text = ResourceService.GetString("Global.CancelButtonText"); + frm.CancelButton = btn; + p.Controls.Add(btn); + + btn = new Button(); + btn.DialogResult = DialogResult.OK; + btn.Text = ResourceService.GetString("Global.OKButtonText"); + frm.AcceptButton = btn; + p.Controls.Add(btn); + + frm.Controls.Add(ed); + frm.Controls.Add(p); + + frm.FormBorderStyle = FormBorderStyle.FixedDialog; + frm.MaximizeBox = false; + frm.MinimizeBox = false; + frm.ClientSize = new Size(400, 300); + frm.StartPosition = FormStartPosition.CenterParent; + + if (frm.ShowDialog(FindForm()) == DialogResult.OK) { + StringBuilder b = new StringBuilder(DefaultRuleAssemblies); + foreach (string asm in ed.GetList()) { + b.Append(';'); + b.Append(asm); + } + this.RuleAssemblies = b.ToString(); + } + } + } } } diff --git a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs index 83e65765e5..4c1ea2942a 100644 --- a/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs +++ b/src/AddIns/Misc/CodeAnalysis/Src/AnalysisProjectOptionsPanel.cs @@ -1,9 +1,9 @@ -/* - * Created by SharpDevelop. - * User: Daniel Grunwald - * Date: 28.02.2006 - * Time: 15:29 - */ +// +// +// +// +// $Revision$ +// using System; using System.Drawing; diff --git a/src/AddIns/Misc/CodeAnalysis/Src/CheckCurrentProjectCommand.cs b/src/AddIns/Misc/CodeAnalysis/Src/CheckCurrentProjectCommand.cs new file mode 100644 index 0000000000..d5be40bdfe --- /dev/null +++ b/src/AddIns/Misc/CodeAnalysis/Src/CheckCurrentProjectCommand.cs @@ -0,0 +1,26 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Project.Commands; + +namespace ICSharpCode.CodeAnalysis +{ + public class CheckCurrentProjectCommand : AbstractMenuCommand + { + public override void Run() + { + IProject p = ProjectService.CurrentProject; + if (p == null) return; + RebuildProject build = new RebuildProject(p); + build.AdditionalProperties.Add("RunCodeAnalysis", "true"); + build.Run(); + } + } +} diff --git a/src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs b/src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs index c94661329d..02b1734cb9 100644 --- a/src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs +++ b/src/AddIns/Misc/CodeAnalysis/Src/FxCopRule.cs @@ -1,9 +1,9 @@ -/* - * Created by SharpDevelop. - * User: Daniel Grunwald - * Date: 28.02.2006 - * Time: 17:16 - */ +// +// +// +// +// $Revision$ +// using System; using System.Collections.Generic; @@ -67,6 +67,8 @@ namespace ICSharpCode.CodeAnalysis FxCopRule o = (FxCopRule)obj; int r = categoryName.CompareTo(o.categoryName); if (r != 0) return r; + r = checkId.CompareTo(o.checkId); + if (r != 0) return r; return displayName.CompareTo(o.displayName); } } @@ -74,16 +76,11 @@ namespace ICSharpCode.CodeAnalysis 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 { @@ -94,7 +91,7 @@ namespace ICSharpCode.CodeAnalysis public string DisplayName { get { - return displayName; + return name; } } diff --git a/src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs b/src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs index 4420591936..cc1c6b38a4 100644 --- a/src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs +++ b/src/AddIns/Misc/CodeAnalysis/Src/FxCopWrapper.cs @@ -1,9 +1,9 @@ -/* - * Created by SharpDevelop. - * User: Daniel Grunwald - * Date: 28.02.2006 - * Time: 16:24 - */ +// +// +// +// +// $Revision$ +// using System; using System.Collections; @@ -17,8 +17,40 @@ namespace ICSharpCode.CodeAnalysis { public static class FxCopWrapper { - static List rules = new List(); - static List>> callbacks = new List>>(); + static Dictionary> ruleDict = new Dictionary>(new ArrayHashCodeProvider()); + + class ArrayHashCodeProvider : IEqualityComparer + { + public bool Equals(string[] x, string[] y) + { + if (x == y) return true; + if (x == null || y == null) return false; + if (x.Length != y.Length) return false; + for (int i = 0; i < x.Length; i++) { + if (StringComparer.OrdinalIgnoreCase.Equals(x[i], y[i])) return false; + } + return true; + } + public int GetHashCode(string[] obj) + { + int hashcode = 0; + foreach (string e in obj) { + hashcode ^= StringComparer.OrdinalIgnoreCase.GetHashCode(e); + } + return hashcode; + } + } + + class Request + { + public string[] ruleAssemblies; + public Action> callback; + public Request(string[] ruleAssemblies, Action> callback) + { + this.ruleAssemblies = ruleAssemblies; + this.callback = callback; + } + } /// /// Gets the rules supported by the current FxCop version. The rules are loaded on a separate @@ -26,20 +58,18 @@ namespace ICSharpCode.CodeAnalysis /// 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) + public static void GetRuleList(string[] ruleAssemblies, 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 (ruleAssemblies == null) + throw new ArgumentNullException("ruleAssemblies"); + List rules = null; + lock (ruleDict) { + if (!ruleDict.TryGetValue(ruleAssemblies, out rules)) { + // Start the thread: + System.Threading.ThreadPool.QueueUserWorkItem(RunGetRuleList, new Request(ruleAssemblies, callback)); } } - if (count > 0) { + if (rules != null) { callback(rules); } } @@ -88,27 +118,26 @@ namespace ICSharpCode.CodeAnalysis static void RunGetRuleList(object state) { + Request request = (Request)state; + LoggingService.Debug("Trying to find FxCop rules"); string fxCopPath = FindFxCopPath(); + List rules; if (fxCopPath != null) { try { - GetRuleListAndSort(fxCopPath); + rules = GetRuleListAndSort(fxCopPath, request.ruleAssemblies); } catch (Exception ex) { LoggingService.Warn(ex); + rules = new List(); } + } else { + rules = new List(); } - 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); - } + LoggingService.Debug("Finished getting FxCop rules, invoking callback"); + request.callback(rules); } - static void GetRuleListAndSort(string fxCopPath) + static List GetRuleListAndSort(string fxCopPath, string[] ruleAssemblies) { AppDomainSetup setup = new AppDomainSetup(); setup.DisallowCodeDownload = true; @@ -117,7 +146,7 @@ namespace ICSharpCode.CodeAnalysis string[][] ruleTextList; try { - ruleTextList = (string[][])AppDomainLaunchHelper.LaunchInAppDomain(domain, typeof(FxCopWrapper), "GetRuleListInCurrentAppDomain", fxCopPath); + ruleTextList = (string[][])AppDomainLaunchHelper.LaunchInAppDomain(domain, typeof(FxCopWrapper), "GetRuleListInCurrentAppDomain", fxCopPath, ruleAssemblies); } finally { AppDomain.Unload(domain); } @@ -130,7 +159,8 @@ namespace ICSharpCode.CodeAnalysis } Array.Sort(ruleList); - lock (rules) { + List rules = new List(); + lock (ruleDict) { FxCopCategory cat = null; foreach (FxCopRule rule in ruleList) { if (cat == null || cat.Name != rule.CategoryName) { @@ -139,7 +169,9 @@ namespace ICSharpCode.CodeAnalysis } cat.Rules.Add(rule); } + ruleDict[ruleAssemblies] = rules; } + return rules; } // We don't want to reference the FxCop assembly @@ -170,13 +202,17 @@ namespace ICSharpCode.CodeAnalysis return v.ToString(); } - public static string[][] GetRuleListInCurrentAppDomain(string fxCopPath) + public static string[][] GetRuleListInCurrentAppDomain(string fxCopPath, string[] ruleAssemblies) { Assembly asm = Assembly.LoadFrom(Path.Combine(fxCopPath, "FxCopCommon.dll")); Type fxCopOM = asm.GetType("Microsoft.FxCop.Common.FxCopOM"); CallMethod(fxCopOM, "Initialize", BindingFlags.Static, null); + object engines = fxCopOM.InvokeMember("Engines", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetProperty, null, null, null); + ((System.Collections.Specialized.StringCollection)GetProp(engines, "RuleDirectories")) + .AddRange(ruleAssemblies); + object project = asm.CreateInstance("Microsoft.FxCop.Common.Project"); fxCopOM.InvokeMember("Project", BindingFlags.Public | BindingFlags.Static | BindingFlags.SetProperty, null, null, new object[] { project }); diff --git a/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.addin b/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.addin index 9c846862ac..3ac1c3d141 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.addin +++ b/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.addin @@ -66,10 +66,9 @@ - + diff --git a/src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs b/src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs index 495a9f6b66..094ef22929 100644 --- a/src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs +++ b/src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs @@ -22,7 +22,7 @@ namespace ICSharpCode.Build.Tasks string logFile; string realLogFile; string inputAssembly; - string rules; + string[] rules; string[] ruleAssemblies; string[] referencePaths; @@ -45,7 +45,7 @@ namespace ICSharpCode.Build.Tasks } } - public string Rules { + public string[] Rules { get { return rules; } @@ -81,7 +81,7 @@ namespace ICSharpCode.Build.Tasks public override bool Execute() { - if (string.IsNullOrEmpty(ToolPath) || !File.Exists(GenerateFullPathToTool())) { + if (string.IsNullOrEmpty(ToolPath)) { string path = FindFxCopPath(); Log.LogMessage(MessageImportance.High, "Running Code Analysis..."); if (path != null) { @@ -96,7 +96,9 @@ namespace ICSharpCode.Build.Tasks bool result = base.Execute(); if (File.Exists(realLogFile)) { try { + #if DEBUG Console.WriteLine(File.ReadAllText(realLogFile)); + #endif XmlDocument doc = new XmlDocument(); doc.Load(realLogFile); foreach (XmlNode node in doc.DocumentElement.SelectNodes(".//Exception")) { @@ -256,10 +258,18 @@ namespace ICSharpCode.Build.Tasks } if (ruleAssemblies != null) { foreach (string asm in ruleAssemblies) { - AppendSwitch(b, "r", asm); + if (asm.StartsWith("\\")) { + AppendSwitch(b, "r", ToolPath + asm); + } else { + AppendSwitch(b, "r", asm); + } + } + } + if (rules != null) { + foreach (string rule in rules) { + AppendSwitch(b, "ruleid", rule); } } - AppendSwitch(b, "rid", rules); return b.ToString(); } } diff --git a/src/Libraries/ICSharpCode.Build.Tasks/Project/SharpDevelop.CodeAnalysis.targets b/src/Libraries/ICSharpCode.Build.Tasks/Project/SharpDevelop.CodeAnalysis.targets index cb62445ec6..89e991995a 100644 --- a/src/Libraries/ICSharpCode.Build.Tasks/Project/SharpDevelop.CodeAnalysis.targets +++ b/src/Libraries/ICSharpCode.Build.Tasks/Project/SharpDevelop.CodeAnalysis.targets @@ -6,7 +6,7 @@ - $(DefineConstants);CODE_ANALYSIS + $(DefineConstants);CODE_ANALYSIS $(FinalDefineConstants),CODE_ANALYSIS=1 diff --git a/src/Main/Base/Project/Src/Commands/BuildCommands.cs b/src/Main/Base/Project/Src/Commands/BuildCommands.cs index 2abb09ffd9..2c29c8f57f 100644 --- a/src/Main/Base/Project/Src/Commands/BuildCommands.cs +++ b/src/Main/Base/Project/Src/Commands/BuildCommands.cs @@ -111,6 +111,14 @@ namespace ICSharpCode.SharpDevelop.Project.Commands } public class BuildProject : AbstractProjectBuildMenuCommand { + IDictionary additionalProperties = new SortedList(); + + public IDictionary AdditionalProperties { + get { + return additionalProperties; + } + } + public BuildProject() { } @@ -121,7 +129,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands public override void StartBuild() { - this.ProjectToBuild.Build(CallbackMethod); + this.ProjectToBuild.Build(CallbackMethod, AdditionalProperties); } public override void AfterBuild() @@ -132,9 +140,12 @@ namespace ICSharpCode.SharpDevelop.Project.Commands public class RebuildProject : BuildProject { + public RebuildProject() {} + public RebuildProject(IProject targetProject) : base(targetProject) {} + public override void StartBuild() { - this.ProjectToBuild.Rebuild(CallbackMethod); + this.ProjectToBuild.Rebuild(CallbackMethod, AdditionalProperties); } } @@ -142,7 +153,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands { public override void StartBuild() { - this.ProjectToBuild.Clean(CallbackMethod); + this.ProjectToBuild.Clean(CallbackMethod, null); } } @@ -150,7 +161,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands { public override void StartBuild() { - this.ProjectToBuild.Publish(CallbackMethod); + this.ProjectToBuild.Publish(CallbackMethod, null); } } diff --git a/src/Main/Base/Project/Src/Gui/Components/StringListEditor.cs b/src/Main/Base/Project/Src/Gui/Components/StringListEditor.cs index 99fcdda1fa..d62ad6332b 100644 --- a/src/Main/Base/Project/Src/Gui/Components/StringListEditor.cs +++ b/src/Main/Base/Project/Src/Gui/Components/StringListEditor.cs @@ -225,6 +225,17 @@ namespace ICSharpCode.SharpDevelop.Gui } } + bool autoAddAfterBrowse; + + public bool AutoAddAfterBrowse { + get { + return autoAddAfterBrowse; + } + set { + autoAddAfterBrowse = value; + } + } + public string TitleText { get { return TitleLabel.Text; @@ -277,6 +288,9 @@ namespace ICSharpCode.SharpDevelop.Gui if (!path.EndsWith("\\") && !path.EndsWith("/")) path += "\\"; editTextBox.Text = path; + if (autoAddAfterBrowse) { + AddButtonClick(null, null); + } } } diff --git a/src/Main/Base/Project/Src/Project/AbstractProject.cs b/src/Main/Base/Project/Src/Project/AbstractProject.cs index 69dc09f414..e192c5f6b8 100644 --- a/src/Main/Base/Project/Src/Project/AbstractProject.cs +++ b/src/Main/Base/Project/Src/Project/AbstractProject.cs @@ -728,19 +728,19 @@ namespace ICSharpCode.SharpDevelop.Project #endregion - public virtual void Build(MSBuildEngineCallback callback) + public virtual void Build(MSBuildEngineCallback callback, IDictionary additionalProperties) { } - public virtual void Rebuild(MSBuildEngineCallback callback) + public virtual void Rebuild(MSBuildEngineCallback callback, IDictionary additionalProperties) { } - public virtual void Clean(MSBuildEngineCallback callback) + public virtual void Clean(MSBuildEngineCallback callback, IDictionary additionalProperties) { } - public virtual void Publish(MSBuildEngineCallback callback) + public virtual void Publish(MSBuildEngineCallback callback, IDictionary additionalProperties) { } diff --git a/src/Main/Base/Project/Src/Project/IProject.cs b/src/Main/Base/Project/Src/Project/IProject.cs index 9886818ded..24dc739bd4 100644 --- a/src/Main/Base/Project/Src/Project/IProject.cs +++ b/src/Main/Base/Project/Src/Project/IProject.cs @@ -138,9 +138,9 @@ namespace ICSharpCode.SharpDevelop.Project /// ProjectItem CreateProjectItem(string itemType); - void Build(MSBuildEngineCallback callback); - void Rebuild(MSBuildEngineCallback callback); - void Clean(MSBuildEngineCallback callback); - void Publish(MSBuildEngineCallback callback); + void Build(MSBuildEngineCallback callback, IDictionary additionalProperties); + void Rebuild(MSBuildEngineCallback callback, IDictionary additionalProperties); + void Clean(MSBuildEngineCallback callback, IDictionary additionalProperties); + void Publish(MSBuildEngineCallback callback, IDictionary additionalProperties); } } diff --git a/src/Main/Base/Project/Src/Project/MSBuildEngine.cs b/src/Main/Base/Project/Src/Project/MSBuildEngine.cs index 0d49fbb1b6..3976d71401 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildEngine.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildEngine.cs @@ -330,7 +330,7 @@ namespace ICSharpCode.SharpDevelop.Project IProjectContent pc = ParserService.GetProjectContent(project); if (pc != null) { Position pos = pc.GetPosition(memberName); - if (pos != null) { + if (pos != null && pos.Cu != null) { file = pos.Cu.FileName ?? ""; lineNumber = pos.Line; columnNumber = pos.Column; diff --git a/src/Main/Base/Project/Src/Project/MSBuildProject.cs b/src/Main/Base/Project/Src/Project/MSBuildProject.cs index e65c61f1eb..77c0399122 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildProject.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildProject.cs @@ -405,7 +405,7 @@ namespace ICSharpCode.SharpDevelop.Project } #endregion - public static void RunMSBuild(string fileName, string target, string configuration, string platform, bool isSingleProject, MSBuildEngineCallback callback) + public static void RunMSBuild(string fileName, string target, string configuration, string platform, bool isSingleProject, MSBuildEngineCallback callback, IDictionary additionalProperties) { WorkbenchSingleton.Workbench.GetPad(typeof(CompilerMessageView)).BringPadToFront(); MSBuildEngine engine = new MSBuildEngine(); @@ -415,6 +415,11 @@ namespace ICSharpCode.SharpDevelop.Project dir += Path.DirectorySeparatorChar; engine.AdditionalProperties.Add("SolutionDir", dir); } + if (additionalProperties != null) { + foreach (KeyValuePair pair in additionalProperties) { + engine.AdditionalProperties.Add(pair.Key, pair.Value); + } + } engine.Configuration = configuration; engine.Platform = platform; engine.MessageView = TaskService.BuildMessageViewCategory; @@ -425,30 +430,30 @@ namespace ICSharpCode.SharpDevelop.Project } } - public void RunMSBuild(string target, MSBuildEngineCallback callback) + public void RunMSBuild(string target, MSBuildEngineCallback callback, IDictionary additionalProperties) { - RunMSBuild(this.FileName, target, this.Configuration, this.Platform, true, callback); + RunMSBuild(this.FileName, target, this.Configuration, this.Platform, true, callback, additionalProperties); } - public override void Build(MSBuildEngineCallback callback) + public override void Build(MSBuildEngineCallback callback, IDictionary additionalProperties) { - RunMSBuild("Build", callback); + RunMSBuild("Build", callback, additionalProperties); } - public override void Rebuild(MSBuildEngineCallback callback) + public override void Rebuild(MSBuildEngineCallback callback, IDictionary additionalProperties) { - RunMSBuild("Rebuild", callback); + RunMSBuild("Rebuild", callback, additionalProperties); } - public override void Clean(MSBuildEngineCallback callback) + public override void Clean(MSBuildEngineCallback callback, IDictionary additionalProperties) { - RunMSBuild("Clean", callback); + RunMSBuild("Clean", callback, additionalProperties); isDirty = true; } - public override void Publish(MSBuildEngineCallback callback) + public override void Publish(MSBuildEngineCallback callback, IDictionary additionalProperties) { - RunMSBuild("Publish", callback); + RunMSBuild("Publish", callback, additionalProperties); } public override string ToString() diff --git a/src/Main/Base/Project/Src/Project/Solution/Solution.cs b/src/Main/Base/Project/Src/Project/Solution/Solution.cs index c2970b23db..35b0b86c7a 100644 --- a/src/Main/Base/Project/Src/Project/Solution/Solution.cs +++ b/src/Main/Base/Project/Src/Project/Solution/Solution.cs @@ -637,29 +637,29 @@ namespace ICSharpCode.SharpDevelop.Project } #endregion - public void RunMSBuild(string target, MSBuildEngineCallback callback) + public void RunMSBuild(string target, MSBuildEngineCallback callback, IDictionary additionalProperties) { - MSBuildProject.RunMSBuild(FileName, target, preferences.ActiveConfiguration, preferences.ActivePlatform, false, callback); + MSBuildProject.RunMSBuild(FileName, target, preferences.ActiveConfiguration, preferences.ActivePlatform, false, callback, additionalProperties); } public void Build(MSBuildEngineCallback callback) { - RunMSBuild(null, callback); + RunMSBuild(null, callback, null); } public void Rebuild(MSBuildEngineCallback callback) { - RunMSBuild("Rebuild", callback); + RunMSBuild("Rebuild", callback, null); } public void Clean(MSBuildEngineCallback callback) { - RunMSBuild("Clean", callback); + RunMSBuild("Clean", callback, null); } public void Publish(MSBuildEngineCallback callback) { - RunMSBuild("Publish", callback); + RunMSBuild("Publish", callback, null); } } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs index 24c13ea348..0bd8994651 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs @@ -822,7 +822,7 @@ namespace ICSharpCode.Core if (curClass != null) { IMember member = curClass.SearchMember(memberName, LanguageProperties.CSharp); if (member != null) { - return new Position(curClass.CompilationUnit, member.Region.BeginLine, member.Region.BeginColumn); + return new Position(member.DeclaringType.CompilationUnit, member.Region.BeginLine, member.Region.BeginColumn); } } } diff --git a/src/Main/GlobalAssemblyInfo.template b/src/Main/GlobalAssemblyInfo.template index 0b8e365ed1..959b75235f 100644 --- a/src/Main/GlobalAssemblyInfo.template +++ b/src/Main/GlobalAssemblyInfo.template @@ -21,7 +21,7 @@ using System.Reflection; [assembly: AssemblyCopyright("2000-2006 AlphaSierraPapa")] [assembly: AssemblyVersion(RevisionClass.Version + "." + RevisionClass.Revision)] -internal class RevisionClass { +internal static class RevisionClass { public const string Version = "2.1.0"; public const string Revision = "-INSERTREVISION-"; }