diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateClassDeclarationAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateClassDeclarationAction.cs index cbfe544d85..446ef81aea 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateClassDeclarationAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateClassDeclarationAction.cs @@ -61,54 +61,73 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (service != null && !service.IsValidName(resolveResult.Identifier, AffectedEntity.Class)) { yield break; } + ClassType classType = GuessClassType (node); - yield return new CodeAction(context.TranslateString("Create class"), script => { - script.CreateNewType(CreateType(context, service, node)); + yield return new CodeAction(classType == ClassType.Interface ? context.TranslateString("Create interface") : context.TranslateString("Create class"), script => { + script.CreateNewType(CreateType(context, service, node, classType)); }); + if (node.Parent is TypeDeclaration || classType == ClassType.Interface) + yield break; yield return new CodeAction(context.TranslateString("Create nested class"), script => { script.InsertWithCursor( context.TranslateString("Create nested class"), Script.InsertPosition.Before, - CreateType(context, service, node) + CreateType(context, service, node, classType) ); }); } - static TypeDeclaration CreateType(RefactoringContext context, NamingConventionService service, AstNode node) + static ClassType GuessClassTypeByName(string identifier) + { + if (identifier.Length > 0 && identifier[0] == 'I' && char.IsUpper (identifier[1])) + return ClassType.Interface; + return ClassType.Class; + } + + static ClassType GuessClassType(AstNode node) + { + if (node is SimpleType) + return GuessClassTypeByName (((SimpleType)node).Identifier); + if (node is IdentifierExpression) + return GuessClassTypeByName (((IdentifierExpression)node).Identifier); + return ClassType.Class; + } + + static TypeDeclaration CreateType(RefactoringContext context, NamingConventionService service, AstNode node, ClassType classType) { TypeDeclaration result; if (node is SimpleType) { - result = CreateClassFromType(context, (SimpleType)node); + result = CreateClassFromType(context, classType, (SimpleType)node); } else if (node is ObjectCreateExpression) { result = CreateClassFromObjectCreation(context, (ObjectCreateExpression)node); } else { - result = CreateClassFromIdentifier(context, (IdentifierExpression)node); + result = CreateClassFromIdentifier(context, classType, (IdentifierExpression)node); } return AddBaseTypesAccordingToNamingRules(context, service, result); } - static TypeDeclaration CreateClassFromIdentifier(RefactoringContext context, IdentifierExpression identifierExpression) + static TypeDeclaration CreateClassFromIdentifier(RefactoringContext context, ClassType classType, IdentifierExpression identifierExpression) { - var result = new TypeDeclaration { Name = identifierExpression.Identifier }; + var result = new TypeDeclaration { Name = identifierExpression.Identifier, ClassType = classType }; var entity = identifierExpression.GetParent(); if (entity != null) result.Modifiers |= entity.Modifiers & Modifiers.Public; return result; } - static TypeDeclaration CreateClassFromType(RefactoringContext context, SimpleType simpleType) + static TypeDeclaration CreateClassFromType(RefactoringContext context, ClassType classType, SimpleType simpleType) { TypeDeclaration result; string className = simpleType.Identifier; - if (simpleType.Parent is Attribute) { + if (simpleType.Parent is Attribute && classType == ClassType.Class) { if (!className.EndsWith("Attribute", System.StringComparison.Ordinal)) className += "Attribute"; } - result = new TypeDeclaration { Name = className }; + result = new TypeDeclaration { Name = className, ClassType = classType }; var entity = simpleType.GetParent(); if (entity != null) result.Modifiers |= entity.Modifiers & Modifiers.Public; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateClassDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateClassDeclarationTests.cs index 1aae1d7129..2b2ab2d0ed 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateClassDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateClassDeclarationTests.cs @@ -26,6 +26,7 @@ using System; using NUnit.Framework; using ICSharpCode.NRefactory.CSharp.Refactoring; +using System.Linq; namespace ICSharpCode.NRefactory.CSharp.CodeActions { @@ -62,7 +63,7 @@ class TestClass "); } - [Test()] + [Test] public void TestNestedCreateClass() { Test( @@ -92,7 +93,7 @@ class TestClass ", 1); } - [Test()] + [Test] public void TestEmptyConstructor () { Test ( @@ -118,7 +119,7 @@ class TestClass "); } - [Test()] + [Test] public void TestCreatePublicEventArgs () { Test ( @@ -138,7 +139,7 @@ class TestClass "); } - [Test()] + [Test] public void TestCreateInternalEventArgs () { Test ( @@ -158,7 +159,7 @@ class TestClass "); } - [Test()] + [Test] public void TestCreateAttribute () { Test ( @@ -178,7 +179,7 @@ class TestClass "); } - [Test()] + [Test] public void TestCreateAttributeCase2 () { Test ( @@ -198,7 +199,7 @@ class TestClass "); } - [Test()] + [Test] public void TestCreateException () { Test ( @@ -348,5 +349,49 @@ class TestClass "); } + + /// + /// Bug 10671 - Auto-Fix of Base Class is wrong (generates invalid code) + /// + [Test] + public void TestBug10671 () + { + var input = @" +namespace TestConsole +{ + public class Test : $BaseMissing + { + } +} +"; + // action allowed to create a nested class + var context = TestRefactoringContext.Create (input, false); + var actions = new CreateClassDeclarationAction().GetActions (context); + Assert.AreEqual (1, actions.Count ()); + } + + + [Test] + public void TestCreateInterface () + { + Test ( + @" +class TestClass +{ + private readonly $IFoo _foo; +} +", @" +interface IFoo +{ +} +class TestClass +{ + private readonly IFoo _foo; +} +"); + } + + + } }