diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs index 750b80b31e..7fc3a8e3c3 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceAction.cs @@ -32,7 +32,7 @@ using System.Linq; namespace ICSharpCode.NRefactory.CSharp.Refactoring { -// [ContextAction("Implement interface", Description = "Creates an interface implementation.")] + [ContextAction("Implement interface", Description = "Creates an interface implementation.")] public class ImplementInterfaceAction : ICodeActionProvider { public IEnumerable GetActions(RefactoringContext context) @@ -48,9 +48,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring var resolveResult = context.Resolve(type); if (resolveResult.Type.Kind != TypeKind.Interface) yield break; + var toImplement = CollectMembersToImplement(state.CurrentTypeDefinition, resolveResult.Type, false); if (toImplement.Count == 0) yield break; + yield return new CodeAction(context.TranslateString("Implement interface"), script => { script.InsertWithCursor( context.TranslateString ("Implement Interface"), @@ -60,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring }); } - public static IEnumerable GenerateImplementation(RefactoringContext context, List> toImplement) + public static IEnumerable GenerateImplementation(RefactoringContext context, IEnumerable> toImplement) { var nodes = new Dictionary>(); @@ -116,6 +118,29 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring foreach (var typeParam in method.TypeParameters) { result.TypeParameters.Add(new TypeParameterDeclaration(typeParam.Name)); + + var constraint = new Constraint() { + TypeParameter = new SimpleType(typeParam.Name) + }; + + if (typeParam.HasDefaultConstructorConstraint) { + constraint.BaseTypes.Add (new PrimitiveType("new")); + } else if (typeParam.HasReferenceTypeConstraint) { + constraint.BaseTypes.Add (new PrimitiveType("class")); + } else if (typeParam.HasValueTypeConstraint) { + constraint.BaseTypes.Add (new PrimitiveType("struct")); + } + + foreach (var type in typeParam.DirectBaseTypes) { + if (type.FullName == "System.Object") + continue; + if (type.FullName == "System.ValueType") + continue; + constraint.BaseTypes.Add (context.CreateShortType (type)); + } + if (constraint.BaseTypes.Count == 0) + continue; + result.Constraints.Add (constraint); } foreach (var p in method.Parameters) { @@ -141,6 +166,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring var def = interfaceType.GetDefinition(); List> toImplement = new List>(); bool alreadyImplemented; + // Stub out non-implemented events defined by @iface foreach (var ev in interfaceType.GetEvents (e => !e.IsSynthetic && e.DeclaringTypeDefinition.ReflectionName == def.ReflectionName)) { bool needsExplicitly = explicitly; @@ -151,9 +177,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (!alreadyImplemented) toImplement.Add(new Tuple(ev, needsExplicitly)); } - + Console.WriteLine("foo!!!!"); // Stub out non-implemented methods defined by @iface - foreach (var method in interfaceType.GetMethods (d => !d.IsSynthetic && d.DeclaringTypeDefinition.ReflectionName == def.ReflectionName)) { + foreach (var method in interfaceType.GetMethods (d => !d.IsSynthetic /* && d.DeclaringTypeDefinition.ReflectionName == def.ReflectionName*/)) { bool needsExplicitly = explicitly; alreadyImplemented = false; @@ -165,6 +191,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring alreadyImplemented |= !needsExplicitly /*|| cmet.InterfaceImplementations.Any (impl => impl.InterfaceType.Equals (interfaceType))*/; } } + if (toImplement.Where (t => t.Item1 is IMethod).Any (t => CompareMethods (method, (IMethod)t.Item1))) + needsExplicitly = true; if (!alreadyImplemented) toImplement.Add(new Tuple(method, needsExplicitly)); } diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceExplicitAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceExplicitAction.cs index 524a4be297..d5206d5ed5 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceExplicitAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ImplementInterfaceExplicitAction.cs @@ -32,7 +32,7 @@ using System.Linq; namespace ICSharpCode.NRefactory.CSharp.Refactoring { -// [ContextAction("Implement interface explicit", Description = "Creates an interface implementation.")] + [ContextAction("Implement interface explicit", Description = "Creates an interface implementation.")] public class ImplementInterfaceExplicitAction : ICodeActionProvider { public IEnumerable GetActions(RefactoringContext context) @@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring script.InsertWithCursor( context.TranslateString("Implement Interface"), state.CurrentTypeDefinition, - ImplementInterfaceAction.GenerateImplementation (context, toImplement) + ImplementInterfaceAction.GenerateImplementation (context, toImplement.Select (t => Tuple.Create (t.Item1, true))) ); }); } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceExplicitTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceExplicitTests.cs index 6ec76d8e9a..1c0fd677cc 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceExplicitTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceExplicitTests.cs @@ -29,7 +29,6 @@ using ICSharpCode.NRefactory.CSharp.Refactoring; namespace ICSharpCode.NRefactory.CSharp.CodeActions { - [Ignore("TODO")] [TestFixture] public class ImplementInterfaceExplicitTests : ContextActionTestBase { @@ -44,9 +43,9 @@ class Foo : $IDisposable class Foo : IDisposable { #region IDisposable implementation - void IDisposable.Dispose() + void IDisposable.Dispose () { - throw new NotImplementedException(); + throw new NotImplementedException (); } #endregion } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceTests.cs index 4a0f9fd770..a204e5f676 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ImplementInterfaceTests.cs @@ -56,7 +56,6 @@ class Foo : IDisposable /// /// Bug 663842 - Interface implementation does not include constraints /// - [Ignore("TODO")] [Test()] public void TestBug663842() { @@ -82,21 +81,21 @@ interface ITest { class Foo : ITest { #region ITest implementation - public void MyMethod1 (T t) where T : new () + public void MyMethod1 (T t) where T : new() { - throw new System.NotImplementedException (); + throw new NotImplementedException (); } public void MyMethod2 (T t) where T : class { - throw new System.NotImplementedException (); + throw new NotImplementedException (); } public void MyMethod3 (T t) where T : struct { - throw new System.NotImplementedException (); + throw new NotImplementedException (); } public void MyMethod4 (T t) where T : IDisposable, IServiceProvider { - throw new System.NotImplementedException (); + throw new NotImplementedException (); } #endregion } @@ -206,7 +205,6 @@ class Foo : ITest /// /// Bug 3365 - MD cannot implement IEnumerable interface correctly - MD cannot implement IEnumerable interface correctly /// - [Ignore("TODO")] [Test()] public void TestBug3365() { @@ -238,20 +236,68 @@ public interface ITest : IA, IEnumerable class Foo : ITest { - #region ITest implementation + #region IA implementation public bool GetEnumerator () { - throw new System.NotImplementedException (); + throw new NotImplementedException (); } #endregion #region IEnumerable implementation - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () + IEnumerator IEnumerable.GetEnumerator () { - throw new System.NotImplementedException (); + throw new NotImplementedException (); } #endregion }"); } + + + /// + /// Bug 4818 - Implement implicit does not handle 'params' types + /// + [Test()] + public void TestBug4818() + { + Test(@"using System; +interface ITest { + void OnScenesAdded (params ITest[] scenes); +} + +class Foo : $ITest +{ +} +", @"using System; +interface ITest { + void OnScenesAdded (params ITest[] scenes); +} + +class Foo : ITest +{ + #region ITest implementation + public void OnScenesAdded (params ITest[] scenes) + { + throw new NotImplementedException (); + } + #endregion +} +"); + + TestWrongContext(@"using System; +interface ITest { + void OnScenesAdded (params ITest[] scenes); +} + +class Foo : $ITest +{ + #region ITest implementation + public void OnScenesAdded (params ITest[] scenes) + { + throw new NotImplementedException (); + } + #endregion +} +"); + } } }