Browse Source

Merge pull request #179 from luiscubal/tdd

Handle type inference ExtractFieldAction
pull/32/merge
Mike Krüger 13 years ago
parent
commit
9ad9d69e3e
  1. 38
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractFieldAction.cs
  2. 114
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractFieldTests.cs
  3. 6
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/TestRefactoringContext.cs

38
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractFieldAction.cs

@ -28,12 +28,15 @@ using System.Collections.Generic; @@ -28,12 +28,15 @@ using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
using Mono.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Extract field", Description = "Extracts a field from a local variable declaration.")]
public class ExtractFieldAction : ICodeActionProvider
{
static readonly AstType varType = new SimpleType ("var");
public IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
//TODO: implement variable assignment & ctor param
@ -42,12 +45,30 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -42,12 +45,30 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
AstType type = varInit.GetPrevNode() as AstType;
if (type == null) yield break;
if (varInit.Parent is FieldDeclaration) yield break;
if (CannotExtractField(varInit)) yield break;
if (CannotExtractField(context, varInit)) yield break;
yield return new CodeAction(context.TranslateString("Assign to new field"), s=>{
var name = varInit.Name;
AstType extractedType;
if (type.IsMatch (varType)) {
IType resolvedType = context.Resolve(varInit.Initializer).Type;
extractedType = context.CreateShortType(resolvedType);
}
else {
extractedType = (AstType) type.Clone();
}
AstNode entityDeclarationNode = varInit.Parent;
while (!(entityDeclarationNode is EntityDeclaration) || (entityDeclarationNode is Accessor)) {
entityDeclarationNode = entityDeclarationNode.Parent;
}
var entity = (EntityDeclaration) entityDeclarationNode;
bool isStatic = entity.HasModifier(Modifiers.Static);
FieldDeclaration field = new FieldDeclaration(){
ReturnType = type.Clone(),
Modifiers = isStatic ? Modifiers.Static : Modifiers.None,
ReturnType = extractedType,
Variables = { new VariableInitializer(name) }
};
AstNode nodeToRemove = RemoveDeclaration(varInit) ? varInit.Parent : type;
@ -83,10 +104,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -83,10 +104,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return result.Variables.First ().Initializer.IsNull;
}
static bool CannotExtractField (VariableInitializer varInit)
static bool CannotExtractField (RefactoringContext context, VariableInitializer varInit)
{
var result = varInit.Parent as VariableDeclarationStatement;
return result == null || result.Variables.Count != 1;
return result == null || result.Variables.Count != 1 || ContainsAnonymousType(context.Resolve(varInit.Initializer).Type);
}
static bool ContainsAnonymousType (IType type)
{
if (type.Kind == TypeKind.Anonymous)
return true;
var arrayType = type as ArrayType;
return arrayType != null && ContainsAnonymousType (arrayType.ElementType);
}
}
}

114
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractFieldTests.cs

@ -141,6 +141,120 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions @@ -141,6 +141,120 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
" }" + Environment.NewLine +
"}", result);
}
[Test]
public void TestConstructor ()
{
Test<ExtractFieldAction>(@"
class TestClass
{
TestClass () {
int $i = 0;
}
}", @"
class TestClass
{
int i;
TestClass () {
i = 0;
}
}");
}
[Test]
public void TestGetter ()
{
Test<ExtractFieldAction>(@"
class TestClass
{
static int X {
get {
int $i = 0;
return i;
}
}
}", @"
class TestClass
{
static int i;
static int X {
get {
i = 0;
return i;
}
}
}");
}
[Test]
public void TestTypeInferenceDeclaration ()
{
Test<ExtractFieldAction> (@"
class TestClass
{
void Test ()
{
var $i = 0;
}
}", @"
class TestClass
{
int i;
void Test ()
{
i = 0;
}
}");
}
[Test]
public void TestTypeInferenceAnonymousType ()
{
TestWrongContext<ExtractFieldAction> (@"
class TestClass
{
void Test ()
{
var $i = new { A = 1 };
}
}
");
}
[Test]
public void TestTypeInferenceAnonymousArrayType ()
{
TestWrongContext<ExtractFieldAction> (@"
class TestClass
{
void Test ()
{
var $i = new [] { new { A = 1 } };
}
}
");
}
[Test]
public void TestStaticField ()
{
Test<ExtractFieldAction> (@"
class TestClass
{
static void Test ()
{
int $i = 0;
}
}", @"
class TestClass
{
static int i;
static void Test ()
{
i = 0;
}
}");
}
}
}

6
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/TestRefactoringContext.cs

@ -104,7 +104,11 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions @@ -104,7 +104,11 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
public override Task InsertWithCursor(string operation, InsertPosition defaultPosition, IEnumerable<AstNode> nodes)
{
var entity = context.GetNode<EntityDeclaration>();
EntityDeclaration entity = context.GetNode<EntityDeclaration>();
if (entity is Accessor) {
entity = (EntityDeclaration) entity.Parent;
}
foreach (var node in nodes) {
InsertBefore(entity, node);
}

Loading…
Cancel
Save