diff --git a/AddIns/ICSharpCode.SharpDevelop.addin b/AddIns/ICSharpCode.SharpDevelop.addin index 03ab7612a2..b2acc58ce4 100644 --- a/AddIns/ICSharpCode.SharpDevelop.addin +++ b/AddIns/ICSharpCode.SharpDevelop.addin @@ -894,24 +894,24 @@ + disabledIcon="Icons.16x16.NavigateBack" + loadclasslazy="false" + class="ICSharpCode.SharpDevelop.Commands.NavigateBack" + > + type="Builder" + class="ICSharpCode.SharpDevelop.Commands.NavigationHistoryMenuBuilder"/> + icon="Icons.16x16.NavigateForward" + tooltip="Navigate Forward" + loadclasslazy="false" + class="ICSharpCode.SharpDevelop.Commands.NavigateForward"/> @@ -1750,7 +1750,7 @@ + class = "SearchAndReplace.FindNextSelected"/> + + + + diff --git a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin index 4eded0b7f8..d2d0bfe7f9 100644 --- a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin +++ b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.addin @@ -33,4 +33,13 @@ taskname = "FxCop" class = "ICSharpCode.CodeAnalysis.FxCopLogger"/> + + + + + + diff --git a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj index 565c0ed9d5..acb8be62f6 100644 --- a/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj +++ b/src/AddIns/Misc/CodeAnalysis/CodeAnalysis.csproj @@ -63,6 +63,7 @@ + @@ -75,6 +76,14 @@ ICSharpCode.Core False + + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} + ICSharpCode.TextEditor + + + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} + NRefactory + \ No newline at end of file diff --git a/src/AddIns/Misc/CodeAnalysis/Src/FxCopLogger.cs b/src/AddIns/Misc/CodeAnalysis/Src/FxCopLogger.cs index 66b9b1ed6b..97bd2a1c8d 100644 --- a/src/AddIns/Misc/CodeAnalysis/Src/FxCopLogger.cs +++ b/src/AddIns/Misc/CodeAnalysis/Src/FxCopLogger.cs @@ -6,9 +6,10 @@ */ using System; -using Microsoft.Build.Framework; +using System.IO; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Project; +using Microsoft.Build.Framework; namespace ICSharpCode.CodeAnalysis { @@ -67,24 +68,32 @@ namespace ICSharpCode.CodeAnalysis void OnError(object sender, BuildErrorEventArgs e) { - AppendError(e.File, e.LineNumber, e.ColumnNumber, e.Code, e.Message, false); + AppendError(e.File, e.LineNumber, e.ColumnNumber, e.Message, false, + e.HelpKeyword, e.Code, e.Subcategory); } void OnWarning(object sender, BuildWarningEventArgs e) { - AppendError(e.File, e.LineNumber, e.ColumnNumber, e.Code, e.Message, true); + AppendError(e.File, e.LineNumber, e.ColumnNumber, e.Message, true, + e.HelpKeyword, e.Code, e.Subcategory); } - void AppendError(string file, int lineNumber, int columnNumber, string code, string message, bool isWarning) + void AppendError(string file, int lineNumber, int columnNumber, + string message, bool isWarning, + string category, string checkId, string subcategory) { + string[] moreData = (subcategory ?? "").Split('|'); BuildError err = engine.CurrentErrorOrWarning; - if (file.StartsWith("positionof#")) { - string memberName = file.Substring(11); - file = ""; - IProject project = ProjectService.GetProject(engine.CurrentProjectFile); - if (project != null) { - IProjectContent pc = ParserService.GetProjectContent(project); - if (pc != null) { + if (Path.GetFileName(file) == "SharpDevelop.CodeAnalysis.targets") { + err.FileName = null; + } + IProject project = ProjectService.GetProject(engine.CurrentProjectFile); + if (project != null) { + IProjectContent pc = ParserService.GetProjectContent(project); + if (pc != null) { + if (file.StartsWith("positionof#")) { + string memberName = file.Substring(11); + file = ""; Position pos = pc.GetPosition(memberName); if (pos != null && pos.Cu != null) { err.FileName = pos.Cu.FileName ?? ""; @@ -92,9 +101,67 @@ namespace ICSharpCode.CodeAnalysis err.Column = pos.Column; } } + + if (moreData.Length > 0 && moreData[0].Length > 0) { + err.Tag = new FxCopTaskTag(pc, moreData[0], category, checkId); + err.ContextMenuAddInTreeEntry = "/SharpDevelop/Pads/ErrorList/CodeAnalysisTaskContextMenu"; + if (moreData.Length > 1) { + (err.Tag as FxCopTaskTag).MessageID = moreData[1]; + } + } } } } } } + + public class FxCopTaskTag + { + IProjectContent projectContent; + string memberName; + string category; + string checkID; + string messageID; + + public IProjectContent ProjectContent { + get { + return projectContent; + } + } + + public string MemberName { + get { + return memberName; + } + } + + public string Category { + get { + return category; + } + } + + public string CheckID { + get { + return checkID; + } + } + + public string MessageID { + get { + return messageID; + } + set { + messageID = value; + } + } + + public FxCopTaskTag(IProjectContent projectContent, string memberName, string category, string checkID) + { + this.projectContent = projectContent; + this.memberName = memberName; + this.category = category; + this.checkID = checkID; + } + } } diff --git a/src/AddIns/Misc/CodeAnalysis/Src/SuppressMessageCommand.cs b/src/AddIns/Misc/CodeAnalysis/Src/SuppressMessageCommand.cs new file mode 100644 index 0000000000..e91df0e0bc --- /dev/null +++ b/src/AddIns/Misc/CodeAnalysis/Src/SuppressMessageCommand.cs @@ -0,0 +1,101 @@ +/* + * Created by SharpDevelop. + * User: Daniel Grunwald + * Date: 19.07.2006 + * Time: 17:57 + */ + +using System; +using System.Collections.Generic; +using System.Text; + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Refactoring; +using ICSharpCode.TextEditor.Document; +using Ast = ICSharpCode.NRefactory.Parser.Ast; + +namespace ICSharpCode.CodeAnalysis +{ + public class SuppressMessageCommand : AbstractMenuCommand + { + public override void Run() + { + TaskView view = (TaskView)Owner; + foreach (Task t in new List(view.SelectedTasks)) { + FxCopTaskTag tag = t.Tag as FxCopTaskTag; + if (tag == null) + continue; + CodeGenerator codegen = tag.ProjectContent.Language.CodeGenerator; + if (codegen == null) + continue; + Position p = tag.ProjectContent.GetPosition(tag.MemberName); + if (p == null || p.Cu == null || p.Cu.FileName == null || p.Line <= 0) + continue; + IWorkbenchWindow window = FileService.OpenFile(p.Cu.FileName); + if (window == null) + continue; + ITextEditorControlProvider provider = window.ViewContent as ITextEditorControlProvider; + if (provider == null) + continue; + IDocument document = provider.TextEditorControl.Document; + if (p.Line >= document.TotalNumberOfLines) + continue; + LineSegment line = document.GetLineSegment(p.Line - 1); + StringBuilder indentation = new StringBuilder(); + for (int i = line.Offset; i < document.TextLength; i++) { + char c = document.GetCharAt(i); + if (c == ' ' || c == '\t') + indentation.Append(c); + else + break; + } + string code = codegen.GenerateCode(CreateSuppressAttribute(p.Cu, tag), indentation.ToString()); + if (!code.EndsWith("\n")) code += Environment.NewLine; + document.Insert(line.Offset, code); + TaskService.Remove(t); + ParserService.ParseViewContent(window.ViewContent); + } + } + + const string NamespaceName = "System.Diagnostics.CodeAnalysis"; + const string AttributeName = "SuppressMessage"; + + static Ast.AbstractNode CreateSuppressAttribute(ICompilationUnit cu, FxCopTaskTag tag) + { + //System.Diagnostics.CodeAnalysis.SuppressMessageAttribute + bool importedCodeAnalysis = CheckImports(cu.ProjectContent.DefaultImports); + if (importedCodeAnalysis == false) { + foreach (IUsing u in cu.Usings) { + if (CheckImports(u)) { + importedCodeAnalysis = true; + break; + } + } + } + + // [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId:="fileIdentifier"] + Ast.Attribute a = new Ast.Attribute(importedCodeAnalysis ? AttributeName : NamespaceName + "." + AttributeName, null, null); + a.PositionalArguments.Add(new Ast.PrimitiveExpression(tag.Category, tag.Category)); + a.PositionalArguments.Add(new Ast.PrimitiveExpression(tag.CheckID, tag.CheckID)); + if (tag.MessageID != null) { + a.NamedArguments.Add(new Ast.NamedArgumentExpression("MessageId", + new Ast.PrimitiveExpression(tag.MessageID, tag.MessageID))); + } + + Ast.AttributeSection sec = new Ast.AttributeSection(null, null); + sec.Attributes.Add(a); + return sec; + } + + static bool CheckImports(IUsing u) + { + if (u == null) + return false; + else + return u.Usings.Contains(NamespaceName); + } + } +} diff --git a/src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs b/src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs index 094ef22929..0acde41253 100644 --- a/src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs +++ b/src/Libraries/ICSharpCode.Build.Tasks/Project/FxCop.cs @@ -155,33 +155,37 @@ namespace ICSharpCode.Build.Tasks string issueLine = issueEl.GetAttribute("Line"); int issueLineNumber = 0; string issueFullFile = null; + + // Try to find additional information about this type + string memberName = null; + XmlNode parent = message.ParentNode; + while (parent != null) { + if (parent.Name == "Member" || parent.Name == "Type" || parent.Name == "Namespace") { + if (memberName == null) + memberName = ((XmlElement)parent).GetAttribute("Name"); + else + memberName = ((XmlElement)parent).GetAttribute("Name") + "." + memberName; + } + parent = parent.ParentNode; + } if (issuePath.Length > 0 && issueLine.Length > 0 && issueFile.Length > 0) { issueFullFile = Path.Combine(issuePath, issueFile); issueLineNumber = int.Parse(issueLine, CultureInfo.InvariantCulture); - } else { - // Try to find additional information about this type - string memberName = null; - XmlNode parent = message.ParentNode; - while (parent != null) { - if (parent.Name == "Member" || parent.Name == "Type" || parent.Name == "Namespace") { - if (memberName == null) - memberName = ((XmlElement)parent).GetAttribute("Name"); - else - memberName = ((XmlElement)parent).GetAttribute("Name") + "." + memberName; - } - parent = parent.ParentNode; - } - if (memberName != null) { - issueFullFile = "positionof#" + memberName; - } + } else if (memberName != null) { + issueFullFile = "positionof#" + memberName; } - issueText = checkId + " : " + category + " : " + issueText; + if (message.HasAttribute("TypeName")) { + checkId = checkId + ":" + message.GetAttribute("TypeName"); + } + if (message.HasAttribute("Id")) { + memberName = memberName + "|" + message.GetAttribute("Id"); + } if (isWarning) { - Log.LogWarning(null, null, checkId, issueFullFile, issueLineNumber, 0, 0, 0, issueText); + Log.LogWarning(memberName, checkId, category, issueFullFile, issueLineNumber, 0, 0, 0, issueText); } else { - Log.LogError(null, null, checkId, issueFullFile, issueLineNumber, 0, 0, 0, issueText); + Log.LogError(memberName, checkId, category, issueFullFile, issueLineNumber, 0, 0, 0, issueText); } } return isWarning; diff --git a/src/Main/Base/Project/Src/Gui/Pads/ErrorList/ErrorListPad.cs b/src/Main/Base/Project/Src/Gui/Pads/ErrorList/ErrorListPad.cs index 37a0583a59..b11fb62f12 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ErrorList/ErrorListPad.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ErrorList/ErrorListPad.cs @@ -13,7 +13,7 @@ using ICSharpCode.SharpDevelop.Project; namespace ICSharpCode.SharpDevelop.Gui { - public class ErrorListPad : AbstractPadContent + public class ErrorListPad : AbstractPadContent, IClipboardHandler { static ErrorListPad instance; public static ErrorListPad Instance { @@ -210,5 +210,36 @@ namespace ICSharpCode.SharpDevelop.Gui taskView.EndUpdate(); UpdateToolstripStatus(); } + + #region IClipboardHandler interface implementation + public bool EnableCut { + get { return false; } + } + public bool EnableCopy { + get { return taskView.TaskIsSelected; } + } + public bool EnablePaste { + get { return false; } + } + public bool EnableDelete { + get { return false; } + } + public bool EnableSelectAll { + get { return true; } + } + + public void Cut() {} + public void Paste() {} + public void Delete() {} + + public void Copy() + { + taskView.CopySelectionToClipboard(); + } + public void SelectAll() + { + taskView.SelectAll(); + } + #endregion } } diff --git a/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs b/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs index 91c18ec69b..78c17a657f 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs @@ -7,17 +7,12 @@ using System; using System.Windows.Forms; -using System.Drawing; -using System.CodeDom.Compiler; -using System.Collections; -using System.IO; -using System.Diagnostics; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Project; namespace ICSharpCode.SharpDevelop.Gui { - public class TaskListPad : AbstractPadContent + public class TaskListPad : AbstractPadContent, IClipboardHandler { TaskView taskView = new TaskView(); @@ -56,8 +51,6 @@ namespace ICSharpCode.SharpDevelop.Gui taskView.ClearTasks(); } - public CompilerResults CompilerResults = null; - void TaskServiceCleared(object sender, EventArgs e) { taskView.ClearTasks(); @@ -87,6 +80,37 @@ namespace ICSharpCode.SharpDevelop.Gui taskView.Invoke(new EventHandler(InternalShowResults)); // SelectTaskView(null, null); } + + #region IClipboardHandler interface implementation + public bool EnableCut { + get { return false; } + } + public bool EnableCopy { + get { return taskView.TaskIsSelected; } + } + public bool EnablePaste { + get { return false; } + } + public bool EnableDelete { + get { return false; } + } + public bool EnableSelectAll { + get { return true; } + } + + public void Cut() {} + public void Paste() {} + public void Delete() {} + + public void Copy() + { + taskView.CopySelectionToClipboard(); + } + public void SelectAll() + { + taskView.SelectAll(); + } + #endregion } } diff --git a/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskView.cs b/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskView.cs index d4fe1c62b6..b632264f9f 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskView.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskView.cs @@ -10,7 +10,10 @@ using System; using System.Collections; +using System.Collections.Generic; +using System.Drawing; using System.IO; +using System.Text; using System.Windows.Forms; namespace ICSharpCode.Core @@ -50,6 +53,48 @@ namespace ICSharpCode.Core } } + public IEnumerable SelectedTasks { + get { + foreach (ListViewItem item in this.SelectedItems) { + yield return (Task)item.Tag; + } + } + } + + public void CopySelectionToClipboard() + { + StringBuilder b = new StringBuilder(); + foreach (Task t in this.SelectedTasks) { + if (b.Length > 0) b.AppendLine(); + b.Append(t.Description); + if (!string.IsNullOrEmpty(t.FileName)) { + b.Append(" - "); + b.Append(t.FileName); + if (t.Line >= 0) { + b.Append(':'); + b.Append(t.Line + 1); + if (t.Column > 0) { + b.Append(','); + b.Append(t.Column + 1); + } + } + } + } + ClipboardWrapper.SetText(b.ToString()); + } + + public void SelectAll() + { + BeginUpdate(); + try { + foreach (ListViewItem item in this.Items) { + item.Selected = true; + } + } finally { + EndUpdate(); + } + } + public TaskView() : base() { RefreshColumnNames(); @@ -154,6 +199,35 @@ namespace ICSharpCode.Core currentListViewItem = item; } } + + protected override void WndProc(ref Message m) + { + if (m.Msg == 0x007B) { // handle WM_CONTEXTMENU + if (this.SelectedItems.Count > 0) { + long lParam = m.LParam.ToInt64(); + int x = unchecked((short)(lParam & 0xffff)); + int y = unchecked((short)((lParam & 0xffff0000) >> 16)); + Point pos; + if (x == -1 && y == -1) { + pos = this.SelectedItems[0].Bounds.Location; + pos.X += 30; + pos.Y += 4; + } else { + pos = PointToClient(new Point(x, y)); + } + string entry = ((Task)this.SelectedItems[0].Tag).ContextMenuAddInTreeEntry; + for (int i = 1; i < this.SelectedItems.Count; i++) { + string entry2 = ((Task)this.SelectedItems[i].Tag).ContextMenuAddInTreeEntry; + if (entry2 != entry) { + entry = Task.DefaultContextMenuAddInTreeEntry; + break; + } + } + MenuService.ShowContextMenu(this, entry, this, pos.X, pos.Y); + } + } + base.WndProc(ref m); + } #endregion #region Task Management diff --git a/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs index c3bbaf6c44..7d9f2e3c82 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs @@ -815,25 +815,82 @@ namespace ICSharpCode.Core /// Gets the position of a member in this project content (not a referenced one). /// /// Fully qualified member name (always case sensitive). - public Position GetPosition(string fullMemberName) + public IDecoration GetElement(string fullMemberName) { IClass curClass = GetClass(fullMemberName, 0, LanguageProperties.CSharp, false); if (curClass != null) { - return new Position(curClass.CompilationUnit, curClass.Region.BeginLine, curClass.Region.BeginColumn); + return curClass; } - int pos = fullMemberName.LastIndexOf('.'); + int pos = fullMemberName.IndexOf('('); if (pos > 0) { - string className = fullMemberName.Substring(0, pos); - string memberName = fullMemberName.Substring(pos + 1); - curClass = GetClass(className, 0, LanguageProperties.CSharp, false); - if (curClass != null) { - IMember member = curClass.SearchMember(memberName, LanguageProperties.CSharp); - if (member != null) { - return new Position(member.DeclaringType.CompilationUnit, member.Region.BeginLine, member.Region.BeginColumn); + // is method call + + int colonPos = fullMemberName.LastIndexOf(':'); + if (colonPos > 0) { + fullMemberName = fullMemberName.Substring(0, colonPos); + } + + string memberName = fullMemberName.Substring(0, pos); + int pos2 = memberName.LastIndexOf('.'); + if (pos2 > 0) { + string className = memberName.Substring(0, pos2); + memberName = memberName.Substring(pos2 + 1); + curClass = GetClass(className, 0, LanguageProperties.CSharp, false); + if (curClass != null) { + IMethod firstMethod = null; + foreach (IMethod m in curClass.Methods) { + if (m.Name == memberName) { + if (firstMethod == null) firstMethod = m; + StringBuilder dotnetName = new StringBuilder(m.DotNetName); + dotnetName.Append('('); + for (int i = 0; i < m.Parameters.Count; i++) { + if (i > 0) dotnetName.Append(','); + if (m.Parameters[i].ReturnType != null) { + dotnetName.Append(m.Parameters[i].ReturnType.DotNetName); + } + } + dotnetName.Append(')'); + if (dotnetName.ToString() == fullMemberName) { + return m; + } + } + } + } + } + } else { + pos = fullMemberName.LastIndexOf('.'); + if (pos > 0) { + string className = fullMemberName.Substring(0, pos); + string memberName = fullMemberName.Substring(pos + 1); + curClass = GetClass(className, 0, LanguageProperties.CSharp, false); + if (curClass != null) { + // get first method with that name, but prefer method without parameters + IMethod firstMethod = null; + foreach (IMethod m in curClass.Methods) { + if (m.Name == memberName) { + if (firstMethod == null || m.Parameters.Count == 0) + firstMethod = m; + } + } + return firstMethod; } } } - return new Position(null, -1, -1); + return null; + } + + public Position GetPosition(string fullMemberName) + { + IDecoration d = GetElement(fullMemberName); + IMember m = d as IMember; + IClass c = d as IClass; + if (m != null) { + return new Position(m.DeclaringType.CompilationUnit, m.Region.BeginLine, m.Region.BeginColumn); + } else if (c != null) { + return new Position(c.CompilationUnit, c.Region.BeginLine, c.Region.BeginColumn); + } else { + return new Position(null, -1, -1); + } } #endregion diff --git a/src/Main/Base/Project/Src/Services/ParserService/Position.cs b/src/Main/Base/Project/Src/Services/ParserService/Position.cs index 9dae67f3b2..13b1534cfb 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/Position.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/Position.cs @@ -9,9 +9,6 @@ using ICSharpCode.SharpDevelop.Dom; namespace ICSharpCode.Core { - /// - /// Used in many methods as parameter, to shorten the parameter lists - /// public class Position { int line = -1; diff --git a/src/Main/Base/Project/Src/Services/Tasks/Task.cs b/src/Main/Base/Project/Src/Services/Tasks/Task.cs index 4d823013bf..a94ca99ea1 100644 --- a/src/Main/Base/Project/Src/Services/Tasks/Task.cs +++ b/src/Main/Base/Project/Src/Services/Tasks/Task.cs @@ -23,13 +23,15 @@ namespace ICSharpCode.Core public class Task { + public const string DefaultContextMenuAddInTreeEntry = "/SharpDevelop/Pads/ErrorList/TaskContextMenu"; + string description; string fileName; TaskType type; int line; int column; - object contextMenuOwner; - string contextMenuAddInTreeEntry; + string contextMenuAddInTreeEntry = DefaultContextMenuAddInTreeEntry; + object tag; public override string ToString() { @@ -40,7 +42,7 @@ namespace ICSharpCode.Core type, description); } - + /// /// The line number of the task. Zero-based (text editor coordinate) /// @@ -80,21 +82,21 @@ namespace ICSharpCode.Core } } - public object ContextMenuOwner { + public string ContextMenuAddInTreeEntry { get { - return contextMenuOwner; + return contextMenuAddInTreeEntry; } set { - contextMenuOwner = value; + contextMenuAddInTreeEntry = value; } } - public string ContextMenuAddInTreeEntry { + public object Tag { get { - return contextMenuAddInTreeEntry; + return tag; } set { - contextMenuAddInTreeEntry = value; + tag = value; } } @@ -116,10 +118,12 @@ namespace ICSharpCode.Core if (string.IsNullOrEmpty(error.ErrorCode)) { description = error.ErrorText; } else { - description = error.ErrorText + "(" + error.ErrorCode + ")"; + description = error.ErrorText + " (" + error.ErrorCode + ")"; + } + if (error.ContextMenuAddInTreeEntry != null) { + contextMenuAddInTreeEntry = error.ContextMenuAddInTreeEntry; } - contextMenuAddInTreeEntry = error.ContextMenuAddInTreeEntry; - contextMenuOwner = error; + tag = error.Tag; } public void JumpToPosition()