diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj index b32a7fc61d..0dc77004fd 100644 --- a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj +++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj @@ -243,7 +243,9 @@ + + diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertExplicitToImplicitImplementationAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertExplicitToImplicitImplementationAction.cs new file mode 100644 index 0000000000..0cdc005d04 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertExplicitToImplicitImplementationAction.cs @@ -0,0 +1,64 @@ +// +// ConvertExplicitToImplicitImplementation.cs +// +// Author: +// Mansheng Yang +// +// Copyright (c) 2012 Mansheng Yang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Linq; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + [ContextAction ("Convert explicit to implict implementation", + Description = " Convert explicit implementation of an interface method to implicit implementation")] + public class ConvertExplicitToImplicitImplementationAction : SpecializedCodeAction + { + protected override CodeAction GetAction (RefactoringContext context, MethodDeclaration node) + { + if (node.PrivateImplementationType.IsNull) + return null; + + if (!node.NameToken.Contains (context.Location) && + !node.PrivateImplementationType.Contains(context.Location)) + return null; + + var method = (IMethod)((MemberResolveResult)context.Resolve (node)).Member; + var type = method.DeclaringType; + + // find existing method with the same signature + if (type.GetMethods (m => m.Name == node.Name && m.TypeParameters.Count == method.TypeParameters.Count + && !m.IsExplicitInterfaceImplementation) + .Any (m => ParameterListComparer.Instance.Equals (m.Parameters, method.Parameters))) + return null; + + return new CodeAction (context.TranslateString ("Convert explict to implicit implementation"), + script => + { + var implicitImpl = (MethodDeclaration)node.Clone (); + implicitImpl.PrivateImplementationType = AstType.Null; + script.Replace (node, implicitImpl); + }); + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertImplicitToExplicitImplementationAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertImplicitToExplicitImplementationAction.cs new file mode 100644 index 0000000000..88ab2ec0a4 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertImplicitToExplicitImplementationAction.cs @@ -0,0 +1,60 @@ +// +// ConvertImplicitToExplicitImplementationAction.cs +// +// Author: +// Mansheng Yang +// +// Copyright (c) 2012 Mansheng Yang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + [ContextAction ("Convert implict to explicit implementation", + Description = " Convert implict implementation of an interface method to explicit implementation")] + public class ConvertImplicitToExplicitImplementationAction : SpecializedCodeAction + { + protected override CodeAction GetAction (RefactoringContext context, MethodDeclaration node) + { + if (!node.PrivateImplementationType.IsNull) + return null; + + if (!node.NameToken.Contains (context.Location)) + return null; + + var method = (IMethod)((MemberResolveResult)context.Resolve (node)).Member; + if (method.ImplementedInterfaceMembers.Count != 1 || method.DeclaringType.Kind == TypeKind.Interface) + return null; + + return new CodeAction (context.TranslateString ("Convert implict to explicit implementation"), + script => + { + var explicitImpl = (MethodDeclaration)node.Clone (); + // remove visibility modifier + explicitImpl.Modifiers &= ~Modifiers.VisibilityMask; + var implementedInterface = method.ImplementedInterfaceMembers [0].DeclaringType; + explicitImpl.PrivateImplementationType = context.CreateShortType (implementedInterface); + script.Replace (node, explicitImpl); + }); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertExplicitToImplicitImplementationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertExplicitToImplicitImplementationTests.cs new file mode 100644 index 0000000000..5486559e59 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertExplicitToImplicitImplementationTests.cs @@ -0,0 +1,92 @@ +// +// ConvertExplicitToImplicitImplementationTests.cs +// +// Author: +// Mansheng Yang +// +// Copyright (c) 2012 Mansheng Yang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using ICSharpCode.NRefactory.CSharp.Refactoring; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.CodeActions +{ + [TestFixture] + public class ConvertExplicitToImplicitImplementationTests : ContextActionTestBase + { + [Test] + public void Test () + { + Test (@" +interface ITest +{ + void Method (); +} +class TestClass : ITest +{ + void $ITest.Method () + { + } +}", @" +interface ITest +{ + void Method (); +} +class TestClass : ITest +{ + void Method () + { + } +}"); + } + + [Test] + public void TestExistingMethod () + { + TestWrongContext (@" +interface ITest +{ + void Method (); +} +class TestClass : ITest +{ + void $ITest.Method () + { + } + void Method () + { + } +}"); + } + + [Test] + public void TestNonExplitiImplementation () + { + TestWrongContext (@" +class TestClass +{ + void $Method () + { + } +}"); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertImplicitToExplicittImplementationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertImplicitToExplicittImplementationTests.cs new file mode 100644 index 0000000000..130bee6bd0 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertImplicitToExplicittImplementationTests.cs @@ -0,0 +1,133 @@ +// +// ConvertImplicitToExplicittImplementationTests.cs +// +// Author: +// Mansheng Yang +// +// Copyright (c) 2012 Mansheng Yang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using ICSharpCode.NRefactory.CSharp.Refactoring; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.CodeActions +{ + [TestFixture] + public class ConvertImplicitToExplicittImplementationTests : ContextActionTestBase + { + [Test] + public void Test () + { + Test (@" +interface ITest +{ + void Method (); +} +class TestClass : ITest +{ + void $Method () + { + } +}", @" +interface ITest +{ + void Method (); +} +class TestClass : ITest +{ + void ITest.Method () + { + } +}"); + } + + [Test] + public void TestMultipleInterfaces () + { + TestWrongContext (@" +interface ITest +{ + void Method (); +} +interface ITest2 +{ + void Method (); +} +class TestClass : ITest, ITest2 +{ + void $Method () + { + } +}"); + } + + [Test] + public void TestNonImplicitImplementation () + { + TestWrongContext (@" +class TestClass +{ + void $Method () + { + } +}"); + } + + [Test] + public void TestInterfaceMethod () + { + TestWrongContext (@" +interface ITest +{ + void Method (); +} +interface ITest2 : ITest +{ + void $Method (); +}"); + } + + [Test] + public void TestModifier () + { + Test (@" +interface ITest +{ + void Method (); +} +class TestClass : ITest +{ + public void $Method () + { + } +}", @" +interface ITest +{ + void Method (); +} +class TestClass : ITest +{ + void ITest.Method () + { + } +}"); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index 70d8c4b79a..af7e5dcb0c 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -83,7 +83,9 @@ + +