Browse Source

Refactoring: decoupled code to implement abstract class from building the menus.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6183 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Martin Koníček 15 years ago
parent
commit
2315172e5f
  1. 55
      src/AddIns/Misc/SharpRefactoring/Project/Src/ClassRefactoringSubmenuBuilder.cs
  2. 88
      src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs
  3. 25
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

55
src/AddIns/Misc/SharpRefactoring/Project/Src/ClassRefactoringSubmenuBuilder.cs

@ -161,19 +161,13 @@ namespace SharpRefactoring @@ -161,19 +161,13 @@ namespace SharpRefactoring
{
IAmbience ambience = AmbienceService.GetCurrentAmbience();
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
foreach (var implementInterfaceAction in RefactoringService.GetImplementInterfaceActions(c, explicitImpl)) {
var implementInterfaceA = implementInterfaceAction;
subItems.Add(new MenuCommand(
ambience.Convert(implementInterfaceAction.Interface),
delegate { implementInterfaceA.Execute(); }));
}
MakeMenuItemsFromActions(subItems, RefactoringService.GetImplementInterfaceActions(c, explicitImpl), ambience);
}
void AddImplementAbstractClassCommands(IClass c, List<ToolStripItem> list)
{
List<ToolStripItem> subItems = new List<ToolStripItem>();
AddImplementAbstractClassCommandItems(subItems, c);
if (subItems.Count > 0) {
list.Add(new ICSharpCode.Core.WinForms.Menu("${res:SharpDevelop.Refactoring.ImplementAbstractClass}", subItems.ToArray()));
}
@ -181,37 +175,22 @@ namespace SharpRefactoring @@ -181,37 +175,22 @@ namespace SharpRefactoring
void AddImplementAbstractClassCommandItems(List<ToolStripItem> subItems, IClass c)
{
IAmbience ambience = AmbienceService.GetCurrentAmbience();
IAmbience ambience = c.ProjectContent.Language.GetAmbience();
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
foreach (IReturnType rt in c.BaseTypes) {
IClass abstractClass = rt.GetUnderlyingClass();
if (abstractClass != null && abstractClass.ClassType == ClassType.Class && abstractClass.IsAbstract) {
IReturnType rtCopy = rt; // copy for access by anonymous method
EventHandler eh = delegate {
var d = FindReferencesAndRenameHelper.GetDocument(c);
if (d != null)
ImplementAbstractClass(d, c, rtCopy);
ParserService.ParseCurrentViewContent();
};
subItems.Add(new MenuCommand(ambience.Convert(abstractClass), eh));
}
}
MakeMenuItemsFromActions(subItems, RefactoringService.GetImplementAbstractClassActions(c), ambience);
}
#region Implementation
void ImplementAbstractClass(IDocument document, IClass target, IReturnType abstractClass)
void MakeMenuItemsFromActions(List<ToolStripItem> subItems, IEnumerable<RefactoringService.ImplementAbstractClassAction> actions, IAmbience labelAmbience)
{
CodeGenerator generator = target.ProjectContent.Language.CodeGenerator;
RefactoringDocumentAdapter doc = new RefactoringDocumentAdapter(document);
var pos = doc.OffsetToPosition(doc.PositionToOffset(target.BodyRegion.EndLine, target.BodyRegion.EndColumn) - 1);
ClassFinder context = new ClassFinder(target, pos.Line, pos.Column);
foreach (IMember member in MemberLookupHelper.GetAccessibleMembers(abstractClass, target, LanguageProperties.CSharp, true)
.Where(m => m.IsAbstract && !HasMember(m, target))) {
generator.InsertCodeAtEnd(target.BodyRegion, doc, generator.GetOverridingMethod(member, context));
foreach (var action in actions) {
var actionCopy = action;
subItems.Add(new MenuCommand(
labelAmbience.Convert(actionCopy.ClassToImplement),
delegate { actionCopy.Execute(); }));
}
}
#region Implementation
void Rename(object sender, EventArgs e)
{
MenuCommand item = (MenuCommand)sender;
@ -224,20 +203,6 @@ namespace SharpRefactoring @@ -224,20 +203,6 @@ namespace SharpRefactoring
FindReferencesAndRenameHelper.ExtractInterface((IClass)item.Tag);
}
#endregion
#region Helpers
SignatureComparer comparer = new SignatureComparer();
bool HasMember(IMember member, IClass containingClass)
{
foreach (IMember m in containingClass.AllMembers) {
if (comparer.Equals(member, m))
return true;
}
return false;
}
#endregion
}
}

88
src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs

@ -489,35 +489,73 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -489,35 +489,73 @@ namespace ICSharpCode.SharpDevelop.Refactoring
}
}
}
#endregion
}
/// <summary>
/// Action describing how to add implementation of an interface to a class.
/// </summary>
public class ImplementInterfaceAction
{
public IReturnType Interface { get; private set; }
public IClass TargetClass { get; private set; }
public bool IsExplicitImpl { get; private set; }
/// <summary>
/// Gets actions which can add implementation of abstract classes to this class.
/// </summary>
public static IEnumerable<ImplementAbstractClassAction> GetImplementAbstractClassActions(IClass c)
{
IAmbience ambience = c.ProjectContent.Language.GetAmbience();
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
foreach (IReturnType rt in c.BaseTypes) {
IClass abstractClass = rt.GetUnderlyingClass();
if (abstractClass != null && abstractClass.ClassType == ClassType.Class && abstractClass.IsAbstract) {
IReturnType rtCopy = rt;
yield return new ImplementAbstractClassAction(rtCopy, c);
}
}
}
public void Execute()
/// <summary>
/// Action describing how to add implementation of an abstract class to a class.
/// </summary>
public class ImplementAbstractClassAction
{
var codeGen = TargetClass.ProjectContent.Language.CodeGenerator;
var d = FindReferencesAndRenameHelper.GetDocument(TargetClass);
if (d != null)
codeGen.ImplementInterface(this.Interface, new RefactoringDocumentAdapter(d), this.IsExplicitImpl, this.TargetClass);
ParserService.ParseCurrentViewContent();
public IReturnType ClassToImplement { get; private set; }
public IClass TargetClass { get; private set; }
public virtual void Execute()
{
var d = FindReferencesAndRenameHelper.GetDocument(TargetClass);
if (d == null)
return;
CodeGenerator.ImplementAbstractClass(new RefactoringDocumentAdapter(d), TargetClass, ClassToImplement);
ParserService.ParseCurrentViewContent();
}
public ImplementAbstractClassAction(IReturnType classToImplement, IClass targetClass)
{
if (targetClass == null)
throw new ArgumentNullException("targetClass");
if (classToImplement == null)
throw new ArgumentNullException("interfaceToImplement");
this.ClassToImplement = classToImplement;
this.TargetClass = targetClass;
}
}
public ImplementInterfaceAction(IReturnType interfaceType, IClass targetClass, bool isExplicitImpl)
/// <summary>
/// Action describing how to add implementation of an interface to a class.
/// </summary>
public class ImplementInterfaceAction : ImplementAbstractClassAction
{
if (interfaceType == null)
throw new ArgumentNullException("interfaceType");
if (targetClass == null)
throw new ArgumentNullException("targetClass");
this.Interface = interfaceType;
this.TargetClass = targetClass;
this.IsExplicitImpl = isExplicitImpl;
public bool IsExplicitImpl { get; private set; }
public override void Execute()
{
var codeGen = TargetClass.ProjectContent.Language.CodeGenerator;
var d = FindReferencesAndRenameHelper.GetDocument(TargetClass);
if (d == null)
return;
codeGen.ImplementInterface(this.ClassToImplement, new RefactoringDocumentAdapter(d), this.IsExplicitImpl, this.TargetClass);
ParserService.ParseCurrentViewContent();
}
public ImplementInterfaceAction(IReturnType interfaceToImplement, IClass targetClass, bool isExplicitImpl)
:base(interfaceToImplement, targetClass)
{
this.IsExplicitImpl = isExplicitImpl;
}
}
#endregion
}
}

25
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

@ -722,6 +722,31 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -722,6 +722,31 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
}
#endregion
#region Abstract class implementation
public static void ImplementAbstractClass(IRefactoringDocument doc, IClass target, IReturnType abstractClass)
{
CodeGenerator generator = target.ProjectContent.Language.CodeGenerator;
var pos = doc.OffsetToPosition(doc.PositionToOffset(target.BodyRegion.EndLine, target.BodyRegion.EndColumn) - 1);
ClassFinder context = new ClassFinder(target, pos.Line, pos.Column);
var memberComparer = new SignatureComparer();
foreach (IMember member in MemberLookupHelper.GetAccessibleMembers(abstractClass, target, LanguageProperties.CSharp, true)
.Where(m => m.IsAbstract && !HasMember(m, target, memberComparer))) {
generator.InsertCodeAtEnd(target.BodyRegion, doc, generator.GetOverridingMethod(member, context));
}
}
static bool HasMember(IMember member, IClass containingClass, SignatureComparer comparer)
{
foreach (IMember m in containingClass.AllMembers) {
if (comparer.Equals(member, m))
return true;
}
return false;
}
#endregion
#region Override member
public virtual AttributedNode GetOverridingMethod(IMember baseMember, ClassFinder targetContext)
{

Loading…
Cancel
Save