diff --git a/AddIns/ICSharpCode.SharpDevelop.addin b/AddIns/ICSharpCode.SharpDevelop.addin
index f44fee2328..d6f4790b39 100755
--- a/AddIns/ICSharpCode.SharpDevelop.addin
+++ b/AddIns/ICSharpCode.SharpDevelop.addin
@@ -1726,7 +1726,7 @@
-
+
@@ -1734,7 +1734,7 @@
-
+
diff --git a/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.addin b/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.addin
index aabcb0eb88..bfadd7271d 100644
--- a/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.addin
+++ b/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.addin
@@ -18,14 +18,14 @@
diff --git a/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj b/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj
index b58b3ddf02..595e442e3e 100644
--- a/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj
+++ b/src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj
@@ -69,7 +69,7 @@
Always
-
+
@@ -106,6 +106,7 @@
+
diff --git a/src/AddIns/Misc/SharpRefactoring/Project/Src/ClassCodeGeneratorMenuBuilder.cs b/src/AddIns/Misc/SharpRefactoring/Project/Src/ClassRefactoringSubmenuBuilder.cs
similarity index 59%
rename from src/AddIns/Misc/SharpRefactoring/Project/Src/ClassCodeGeneratorMenuBuilder.cs
rename to src/AddIns/Misc/SharpRefactoring/Project/Src/ClassRefactoringSubmenuBuilder.cs
index 7c8e60c5e5..b987df3508 100644
--- a/src/AddIns/Misc/SharpRefactoring/Project/Src/ClassCodeGeneratorMenuBuilder.cs
+++ b/src/AddIns/Misc/SharpRefactoring/Project/Src/ClassRefactoringSubmenuBuilder.cs
@@ -6,8 +6,9 @@
//
using System;
-using System.Linq;
using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using System.Windows.Forms;
using ICSharpCode.Core;
@@ -19,12 +20,22 @@ using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.SharpDevelop.Editor;
+using ICSharpCode.SharpDevelop.Editor.Commands;
using ICSharpCode.SharpDevelop.Gui.ClassBrowser;
+using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace SharpRefactoring
{
- public class ClassCodeGeneratorMenuBuilder : ISubmenuBuilder, IMenuItemBuilder
+ ///
+ /// Generates items the class submenu.
+ /// Paths:
+ /// /SharpDevelop/ViewContent/DefaultTextEditor/ClassBookmarkContextMenu, id=classCodeGenerators
+ /// /SharpDevelop/Pads/ClassBrowser/ClassContextMenu, id=classCodeGenerators
+ ///
+ /// This builder generates items to the same submenu as .
+ ///
+ public class ClassRefactoringSubmenuBuilder : ISubmenuBuilder, IMenuItemBuilder
{
public System.Collections.ICollection BuildItems(Codon codon, object owner)
{
@@ -35,28 +46,92 @@ namespace SharpRefactoring
{
List resultItems = new List();
- IClass c;
- ClassNode classNode = owner as ClassNode;
- if (classNode != null) {
- c = classNode.Class;
- } else {
- ClassBookmark bookmark = (ClassBookmark)owner;
- c = bookmark.Class;
+ IClass c = ClassBookmarkSubmenuBuilder.GetClass(owner);
+ if (c == null) {
+ return new ToolStripMenuItem[0];
}
-
LanguageProperties language = c.ProjectContent.Language;
- if (language != LanguageProperties.CSharp)
- return resultItems.ToArray();
- AddImplementAbstractClassCommands(c, resultItems);
+ if (language == LanguageProperties.CSharp) {
+ AddImplementAbstractClassCommands(c, resultItems);
+ }
if (c.BaseTypes.Count > 0 && c.ClassType != ClassType.Interface && !FindReferencesAndRenameHelper.IsReadOnly(c)) {
AddImplementInterfaceCommands(c, resultItems);
}
+ if (!FindReferencesAndRenameHelper.IsReadOnly(c)) {
+ AddCorrectClassFileNameCommands(c, resultItems);
+
+ AddRenameCommand(c, resultItems);
+
+ if (language.RefactoringProvider.SupportsExtractInterface) {
+ AddExtractInterfaceCommand(c, resultItems);
+ }
+ }
+
return resultItems.ToArray();
}
+ void AddRenameCommand(IClass c, List resultItems)
+ {
+ var cmd = new MenuCommand("${res:SharpDevelop.Refactoring.RenameCommand}", Rename);
+ cmd.ShortcutKeys = MenuCommand.ParseShortcut("Control|R");
+ cmd.Tag = c;
+ resultItems.Add(cmd);
+ }
+
+ void AddExtractInterfaceCommand(IClass c, List resultItems)
+ {
+ var cmd = new MenuCommand("${res:SharpDevelop.Refactoring.ExtractInterfaceCommand}", ExtractInterface);
+ cmd.Tag = c;
+ resultItems.Add(cmd);
+ }
+
+ void AddCorrectClassFileNameCommands(IClass c, List resultItems)
+ {
+ if (c.DeclaringType == null &&
+ !c.BodyRegion.IsEmpty &&
+ !c.Name.Equals(Path.GetFileNameWithoutExtension(c.CompilationUnit.FileName),
+ StringComparison.OrdinalIgnoreCase))
+ {
+ // File name does not match class name
+ string correctFileName = Path.Combine(Path.GetDirectoryName(c.CompilationUnit.FileName),
+ c.Name + Path.GetExtension(c.CompilationUnit.FileName));
+ if (FileUtility.IsValidPath(correctFileName)
+ && Path.IsPathRooted(correctFileName)
+ && !File.Exists(correctFileName))
+ {
+ if (c.CompilationUnit.Classes.Count == 1) {
+ // Rename file to ##
+ var cmd = new MenuCommand(
+ StringParser.Parse("${res:SharpDevelop.Refactoring.RenameFileTo}",
+ new string[,] {{ "FileName", Path.GetFileName(correctFileName) }}),
+ delegate {
+ IProject p = (IProject)c.ProjectContent.Project;
+ RefactoringHelpers.RenameFile(p, c.CompilationUnit.FileName, correctFileName);
+ if (p != null) {
+ p.Save();
+ }
+ });
+ resultItems.Add(cmd);
+ } else {
+ var refactoringProvider = c.ProjectContent.Language.RefactoringProvider;
+ if (refactoringProvider.SupportsCreateNewFileLikeExisting && refactoringProvider.SupportsGetFullCodeRangeForType) {
+ // Move class to file ##
+ var cmd = new MenuCommand(
+ StringParser.Parse("${res:SharpDevelop.Refactoring.MoveClassToFile}",
+ new string[,] {{ "FileName", Path.GetFileName(correctFileName) }}),
+ delegate {
+ FindReferencesAndRenameHelper.MoveClassToFile(c, correctFileName);
+ });
+ resultItems.Add(cmd);
+ }
+ }
+ }
+ }
+ }
+
void AddImplementInterfaceCommands(IClass c, List list)
{
CodeGenerator codeGen = c.ProjectContent.Language.CodeGenerator;
@@ -129,7 +204,7 @@ namespace SharpRefactoring
}
}
- #region Code generation
+ #region Implementation
void ImplementAbstractClass(IDocument document, IClass target, IReturnType abstractClass)
{
CodeGenerator generator = target.ProjectContent.Language.CodeGenerator;
@@ -142,6 +217,18 @@ namespace SharpRefactoring
generator.InsertCodeAtEnd(target.BodyRegion, doc, generator.GetOverridingMethod(member, context));
}
}
+
+ void Rename(object sender, EventArgs e)
+ {
+ MenuCommand item = (MenuCommand)sender;
+ FindReferencesAndRenameHelper.RenameClass((IClass)item.Tag);
+ }
+
+ void ExtractInterface(object sender, EventArgs e)
+ {
+ MenuCommand item = (MenuCommand)sender;
+ FindReferencesAndRenameHelper.ExtractInterface((IClass)item.Tag);
+ }
#endregion
#region Helpers
diff --git a/src/AddIns/Misc/SharpRefactoring/Project/Src/RefactoringHelpers.cs b/src/AddIns/Misc/SharpRefactoring/Project/Src/RefactoringHelpers.cs
new file mode 100644
index 0000000000..98b3c78836
--- /dev/null
+++ b/src/AddIns/Misc/SharpRefactoring/Project/Src/RefactoringHelpers.cs
@@ -0,0 +1,46 @@
+//
+//
+//
+//
+// $Revision: $
+//
+using System;
+using System.IO;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace SharpRefactoring
+{
+ public class RefactoringHelpers
+ {
+ ///
+ /// Renames file as well as files it is dependent upon.
+ ///
+ public static void RenameFile(IProject p, string oldFileName, string newFileName)
+ {
+ FileService.RenameFile(oldFileName, newFileName, false);
+ if (p != null) {
+ string oldPrefix = Path.GetFileNameWithoutExtension(oldFileName) + ".";
+ string newPrefix = Path.GetFileNameWithoutExtension(newFileName) + ".";
+ foreach (ProjectItem item in p.Items) {
+ FileProjectItem fileItem = item as FileProjectItem;
+ if (fileItem == null)
+ continue;
+ string dependentUpon = fileItem.DependentUpon;
+ if (string.IsNullOrEmpty(dependentUpon))
+ continue;
+ string directory = Path.GetDirectoryName(fileItem.FileName);
+ dependentUpon = Path.Combine(directory, dependentUpon);
+ if (FileUtility.IsEqualFileName(dependentUpon, oldFileName)) {
+ fileItem.DependentUpon = FileUtility.GetRelativePath(directory, newFileName);
+ string fileName = Path.GetFileName(fileItem.FileName);
+ if (fileName.StartsWith(oldPrefix)) {
+ RenameFile(p, fileItem.FileName, Path.Combine(directory, newPrefix + fileName.Substring(oldPrefix.Length)));
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index e73869ce9b..d830c39fb7 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -97,7 +97,7 @@
-
+
diff --git a/src/Main/Base/Project/Src/Editor/Commands/ClassBookmarkMenuBuilder.cs b/src/Main/Base/Project/Src/Editor/Commands/ClassBookmarkSubmenuBuilder.cs
similarity index 60%
rename from src/Main/Base/Project/Src/Editor/Commands/ClassBookmarkMenuBuilder.cs
rename to src/Main/Base/Project/Src/Editor/Commands/ClassBookmarkSubmenuBuilder.cs
index f774dcc478..add472a8e9 100644
--- a/src/Main/Base/Project/Src/Editor/Commands/ClassBookmarkMenuBuilder.cs
+++ b/src/Main/Base/Project/Src/Editor/Commands/ClassBookmarkSubmenuBuilder.cs
@@ -27,62 +27,18 @@ using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Editor.Commands
{
///
- /// Build context menu for class members in the text editor.
+ /// Build context submenu for class members in the text editor.
+ /// Paths:
+ /// /SharpDevelop/ViewContent/DefaultTextEditor/ClassBookmarkContextMenu, id=MenuBuilder
+ /// /SharpDevelop/Pads/ClassBrowser/ClassContextMenu, id=MenuBuilder
///
- public class ClassBookmarkMenuBuilder : ISubmenuBuilder, IMenuItemBuilder
+ public class ClassBookmarkSubmenuBuilder : ISubmenuBuilder, IMenuItemBuilder
{
public System.Collections.ICollection BuildItems(Codon codon, object owner)
{
return BuildSubmenu(codon, owner).TranslateToWpf();
}
- ///
- /// Gets a specific part of the compound class.
- ///
- static IClass GetPart(IClass possibleCompound, string fileName)
- {
- CompoundClass compound = possibleCompound as CompoundClass;
- if (compound == null)
- return possibleCompound;
-
- IList parts = compound.Parts;
- if (!string.IsNullOrEmpty(fileName)) {
- // get the part with the requested file name
- foreach (IClass part in parts) {
- if (FileUtility.IsEqualFileName(fileName, part.CompilationUnit.FileName))
- return part;
- }
- }
-
- // Fallback: get the part with the shortest file name.
- // This should prefer non-designer files over designer files.
- IClass preferredClass = parts[0];
- for (int i = 1; i < parts.Count; i++) {
- if (IsShorterFileName(parts[i].CompilationUnit.FileName, preferredClass.CompilationUnit.FileName))
- preferredClass = parts[i];
- }
- return preferredClass;
- }
-
- static bool IsShorterFileName(string a, string b)
- {
- // Fix forum-17295: compilation unit's file name might be null: prefer the non-null file
- if (a == null)
- return false;
- if (b == null)
- return true;
- return a.Length < b.Length;
- }
-
- static IClass GetCurrentPart(IClass possibleCompound)
- {
- IViewContent viewContent = WorkbenchSingleton.Workbench.ActiveViewContent;
- if (viewContent != null)
- return GetPart(possibleCompound, viewContent.PrimaryFileName);
- else
- return GetPart(possibleCompound, null);
- }
-
public ToolStripItem[] BuildSubmenu(Codon codon, object owner)
{
MenuCommand cmd;
@@ -106,58 +62,6 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
List list = new List();
- // refactoring actions
- if (!FindReferencesAndRenameHelper.IsReadOnly(c)) {
- if (c.DeclaringType == null &&
- !c.BodyRegion.IsEmpty &&
- !c.Name.Equals(Path.GetFileNameWithoutExtension(c.CompilationUnit.FileName),
- StringComparison.OrdinalIgnoreCase))
- {
- // File name does not match class name
- string correctFileName = Path.Combine(Path.GetDirectoryName(c.CompilationUnit.FileName),
- c.Name + Path.GetExtension(c.CompilationUnit.FileName));
- if (FileUtility.IsValidPath(correctFileName)
- && Path.IsPathRooted(correctFileName)
- && !File.Exists(correctFileName))
- {
- if (c.CompilationUnit.Classes.Count == 1) {
- // Rename file to ##
- cmd = new MenuCommand(
- StringParser.Parse("${res:SharpDevelop.Refactoring.RenameFileTo}",
- new string[,] {{ "FileName", Path.GetFileName(correctFileName) }}),
- delegate {
- IProject p = (IProject)c.ProjectContent.Project;
- RenameFile(p, c.CompilationUnit.FileName, correctFileName);
- if (p != null) {
- p.Save();
- }
- });
- list.Add(cmd);
- } else if (language.RefactoringProvider.SupportsCreateNewFileLikeExisting && language.RefactoringProvider.SupportsGetFullCodeRangeForType) {
- // Move class to file ##
- cmd = new MenuCommand(
- StringParser.Parse("${res:SharpDevelop.Refactoring.MoveClassToFile}",
- new string[,] {{ "FileName", Path.GetFileName(correctFileName) }}),
- delegate {
- FindReferencesAndRenameHelper.MoveClassToFile(c, correctFileName);
- });
- list.Add(cmd);
- }
- }
- }
-
- cmd = new MenuCommand("${res:SharpDevelop.Refactoring.RenameCommand}", Rename);
- cmd.ShortcutKeys = MenuCommand.ParseShortcut("Control|R");
- cmd.Tag = c;
- list.Add(cmd);
-
- if (language.RefactoringProvider.SupportsExtractInterface) {
- cmd = new MenuCommand("${res:SharpDevelop.Refactoring.ExtractInterfaceCommand}", ExtractInterface);
- cmd.Tag = c;
- list.Add(cmd);
- }
- }
-
// navigation actions
if (c.BaseTypes.Count > 0) {
list.Add(new MenuSeparator());
@@ -182,38 +86,6 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
return list.ToArray();
}
- static void RenameFile(IProject p, string oldFileName, string newFileName)
- {
- FileService.RenameFile(oldFileName, newFileName, false);
- if (p != null) {
- string oldPrefix = Path.GetFileNameWithoutExtension(oldFileName) + ".";
- string newPrefix = Path.GetFileNameWithoutExtension(newFileName) + ".";
- foreach (ProjectItem item in p.Items) {
- FileProjectItem fileItem = item as FileProjectItem;
- if (fileItem == null)
- continue;
- string dependentUpon = fileItem.DependentUpon;
- if (string.IsNullOrEmpty(dependentUpon))
- continue;
- string directory = Path.GetDirectoryName(fileItem.FileName);
- dependentUpon = Path.Combine(directory, dependentUpon);
- if (FileUtility.IsEqualFileName(dependentUpon, oldFileName)) {
- fileItem.DependentUpon = FileUtility.GetRelativePath(directory, newFileName);
- string fileName = Path.GetFileName(fileItem.FileName);
- if (fileName.StartsWith(oldPrefix)) {
- RenameFile(p, fileItem.FileName, Path.Combine(directory, newPrefix + fileName.Substring(oldPrefix.Length)));
- }
- }
- }
- }
- }
-
- void ExtractInterface(object sender, EventArgs e)
- {
- MenuCommand item = (MenuCommand)sender;
- FindReferencesAndRenameHelper.ExtractInterface((IClass)item.Tag);
- }
-
void GoToBase(object sender, EventArgs e)
{
MenuCommand item = (MenuCommand)sender;
@@ -227,12 +99,6 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
}
}
- void Rename(object sender, EventArgs e)
- {
- MenuCommand item = (MenuCommand)sender;
- FindReferencesAndRenameHelper.RenameClass((IClass)item.Tag);
- }
-
void FindDerivedClasses(object sender, EventArgs e)
{
MenuCommand item = (MenuCommand)sender;
@@ -264,5 +130,69 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
IClass c = (IClass)item.Tag;
FindReferencesAndRenameHelper.RunFindReferences(c);
}
+
+
+ public static IClass GetClass(object menuOwner)
+ {
+ IClass c;
+ ClassNode classNode = menuOwner as ClassNode;
+ if (classNode != null) {
+ c = classNode.Class;
+ } else {
+ ClassBookmark bookmark = (ClassBookmark)menuOwner;
+ c = bookmark.Class;
+ }
+ ParserService.ParseCurrentViewContent();
+ c = c.ProjectContent.GetClass(c.FullyQualifiedName, c.TypeParameters.Count, c.ProjectContent.Language, GetClassOptions.LookForInnerClass);
+ c = GetCurrentPart(c);
+ return c;
+ }
+
+ static IClass GetCurrentPart(IClass possibleCompound)
+ {
+ IViewContent viewContent = WorkbenchSingleton.Workbench.ActiveViewContent;
+ if (viewContent != null)
+ return GetPart(possibleCompound, viewContent.PrimaryFileName);
+ else
+ return GetPart(possibleCompound, null);
+ }
+
+ ///
+ /// Gets a specific part of the compound class.
+ ///
+ static IClass GetPart(IClass possibleCompound, string fileName)
+ {
+ CompoundClass compound = possibleCompound as CompoundClass;
+ if (compound == null)
+ return possibleCompound;
+
+ IList parts = compound.Parts;
+ if (!string.IsNullOrEmpty(fileName)) {
+ // get the part with the requested file name
+ foreach (IClass part in parts) {
+ if (FileUtility.IsEqualFileName(fileName, part.CompilationUnit.FileName))
+ return part;
+ }
+ }
+
+ // Fallback: get the part with the shortest file name.
+ // This should prefer non-designer files over designer files.
+ IClass preferredClass = parts[0];
+ for (int i = 1; i < parts.Count; i++) {
+ if (IsShorterFileName(parts[i].CompilationUnit.FileName, preferredClass.CompilationUnit.FileName))
+ preferredClass = parts[i];
+ }
+ return preferredClass;
+ }
+
+ static bool IsShorterFileName(string a, string b)
+ {
+ // Fix forum-17295: compilation unit's file name might be null: prefer the non-null file
+ if (a == null)
+ return false;
+ if (b == null)
+ return true;
+ return a.Length < b.Length;
+ }
}
}
diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs
index ed3e6be77b..992e59990b 100644
--- a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs
+++ b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs
@@ -46,7 +46,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring
}
///
- /// Build a menu with refactoring commands for the item that has been clicked on in the text editor.
+ /// Build refactoring commands for the item that has been clicked on in the text editor.
+ /// The commands are inserted to the top level of the context menu.
+ /// Path:
+ /// /SharpDevelop/ViewContent/TextEditor/ContextMenu, id=Refactoring
///
public class RefactoringMenuBuilder : IMenuItemBuilder
{