Browse Source

"Implement interface" and "Implement abstract class" editor context menu items are shown only when needed (that is the class/interface is not yet implemented).

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6186 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Martin Koníček 15 years ago
parent
commit
7b318f80a1
  1. 35
      src/AddIns/Misc/SharpRefactoring/Project/Src/Extensions.cs
  2. 16
      src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs
  3. 48
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ExtensionMethods.cs
  4. 14
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

35
src/AddIns/Misc/SharpRefactoring/Project/Src/Extensions.cs

@ -36,40 +36,5 @@ namespace SharpRefactoring @@ -36,40 +36,5 @@ namespace SharpRefactoring
return instance.AllMembers
.SingleOrDefault(m => m.BodyRegion.IsInside(caretLine, caretColumn));
}
/// <summary>
/// Gets all interfaces that this class declares to implement, but its implementations are missing in the class body.
/// </summary>
public static List<IClass> GetInterfacesMissingImplementation(this IClass @class)
{
return null;
}
public static bool ClassImplementsClass(IClass targetClass, IClass baseClass)
{
bool requireAlternativeImplementation;
var targetClassType = targetClass.DefaultReturnType;
var baseClassType = baseClass.DefaultReturnType;
var targetClassMethods = targetClassType.GetMethods();
foreach (var m in baseClassType.GetMethods()) {
if (!CodeGenerator.InterfaceMemberAlreadyImplemented(targetClassMethods, m, out requireAlternativeImplementation)) {
return false;
}
}
var targetClassProperties = targetClassType.GetProperties();
foreach (var p in baseClassType.GetProperties()) {
if (!CodeGenerator.InterfaceMemberAlreadyImplemented(targetClassProperties, p, out requireAlternativeImplementation)) {
return false;
}
}
var targetClassEvents = targetClassType.GetEvents();
foreach (var e in baseClassType.GetEvents()) {
if (!CodeGenerator.InterfaceMemberAlreadyImplemented(targetClassEvents, e, out requireAlternativeImplementation)) {
return false;
}
}
return true;
}
}
}

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

@ -477,13 +477,15 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -477,13 +477,15 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// <summary>
/// Gets actions which can add implementation of interface to this class.
/// </summary>
public static IEnumerable<ImplementInterfaceAction> GetImplementInterfaceActions(IClass c, bool isExplicitImpl)
public static IEnumerable<ImplementInterfaceAction> GetImplementInterfaceActions(IClass c, bool isExplicitImpl, bool returnMissingInterfacesOnly = true)
{
IAmbience ambience = c.ProjectContent.Language.GetAmbience();
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
foreach (IReturnType rt in c.BaseTypes) {
IClass interf = rt.GetUnderlyingClass();
if (interf != null && interf.ClassType == ClassType.Interface) {
if (returnMissingInterfacesOnly && c.ImplementsInterface(interf)) {
// this interface is already implemented
continue;
}
IReturnType rtCopy = rt;
yield return new ImplementInterfaceAction(rtCopy, c, isExplicitImpl);
}
@ -492,13 +494,15 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -492,13 +494,15 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// <summary>
/// Gets actions which can add implementation of abstract classes to this class.
/// </summary>
public static IEnumerable<ImplementAbstractClassAction> GetImplementAbstractClassActions(IClass c)
public static IEnumerable<ImplementAbstractClassAction> GetImplementAbstractClassActions(IClass c, bool returnMissingClassesOnly = true)
{
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) {
if (returnMissingClassesOnly && c.ImplementsAbstractClass(abstractClass)) {
// this interface is already implemented
continue;
}
IReturnType rtCopy = rt;
yield return new ImplementAbstractClassAction(rtCopy, c);
}

48
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ExtensionMethods.cs

@ -12,9 +12,6 @@ using System.Linq; @@ -12,9 +12,6 @@ using System.Linq;
namespace ICSharpCode.SharpDevelop.Dom
{
/// <summary>
/// Description of ExtensionMethods.
/// </summary>
static class ExtensionMethods
{
public static void AddRange(this ArrayList arrayList, IEnumerable elements)
@ -63,4 +60,49 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -63,4 +60,49 @@ namespace ICSharpCode.SharpDevelop.Dom
return (new[]{cu.UsingScope}).Flatten(s=>s.ChildScopes).SelectMany(s=>s.Usings);
}
}
/// <summary>
/// Publicly visible helper methods.
/// </summary>
public static class ExtensionMethodsPublic
{
// the difference between IClass and IReturnType is that IClass only contains the members
// that are declared in this very class,
// and IReturnType contains also members from base classes (including System.Object) and default (undeclared) constructors
static SignatureComparer memberSignatureComparer = new SignatureComparer();
public static bool HasMember(this IClass containingClass, IMember member)
{
return containingClass.AllMembers.Any(m => memberSignatureComparer.Equals(member, m));
}
public static bool HasMember(this IReturnType containingClass, IMember member)
{
return containingClass.GetMembers().Any(m => memberSignatureComparer.Equals(member, m));
}
public static bool ImplementsInterface(this IClass targetClass, IClass requiredInterface)
{
var targetClassType = targetClass.GetCompoundClass().DefaultReturnType;
var requiredInterfaceType = requiredInterface.GetCompoundClass().DefaultReturnType;
// class.DefaultReturnType.GetMethods() returns also methods from base classes, default ctor, ToString() etc. etc.
return !requiredInterfaceType.GetMembers().Any(missingMember => !targetClassType.HasMember(missingMember));
}
public static bool ImplementsAbstractClass(this IClass targetClass, IClass abstractClass)
{
var requiredAbstractMembers = MemberLookupHelper.GetAccessibleMembers(abstractClass.DefaultReturnType, targetClass, LanguageProperties.CSharp, true).Where(m => m.IsAbstract);
return !requiredAbstractMembers.Any(missingMember => !targetClass.HasMember(missingMember));
}
public static IEnumerable<IMember> GetMembers(this IReturnType typeReference)
{
var properties = typeReference.GetProperties().Cast<IMember>();
var methods = typeReference.GetMethods().Cast<IMember>();
var fields = typeReference.GetFields().Cast<IMember>();
var events = typeReference.GetEvents().Cast<IMember>();
return properties.Concat(methods).Concat(fields).Concat(events);
}
}
}

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

@ -608,6 +608,7 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -608,6 +608,7 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
return copy;
}
// FIXME this whole method could be probably replaced by DOM.ExtensionMethodsPublic.HasMember
public static bool InterfaceMemberAlreadyImplemented<T>(IEnumerable<T> existingMembers, T interfaceMember,
out bool requireAlternativeImplementation)
where T : class, IMember
@ -728,23 +729,12 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -728,23 +729,12 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
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))) {
.Where(m => m.IsAbstract && !target.HasMember(m))) {
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

Loading…
Cancel
Save