Browse Source

Fixed bug in extract method.

pull/32/merge
Mike Krüger 13 years ago
parent
commit
e29ddf05c8
  1. 25
      ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/VariableUsageAnalyzation.cs
  2. 72
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractMethodTests.cs
  3. 4
      ICSharpCode.NRefactory.Tests/CSharp/CodeActions/TestRefactoringContext.cs

25
ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/VariableUsageAnalyzation.cs

@ -27,6 +27,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{ {
@ -40,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
public class VariableUsageAnalyzation : DepthFirstAstVisitor public class VariableUsageAnalyzation : DepthFirstAstVisitor
{ {
// readonly RefactoringContext context; readonly RefactoringContext context;
readonly List<IVariable> usedVariables; readonly List<IVariable> usedVariables;
Dictionary<IVariable, VariableState> states = new Dictionary<IVariable, VariableState> (); Dictionary<IVariable, VariableState> states = new Dictionary<IVariable, VariableState> ();
@ -50,7 +51,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
public VariableUsageAnalyzation (RefactoringContext context, List<IVariable> usedVariables) public VariableUsageAnalyzation (RefactoringContext context, List<IVariable> usedVariables)
{ {
// this.context = context; this.context = context;
this.usedVariables = usedVariables; this.usedVariables = usedVariables;
} }
@ -95,6 +96,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
public override void VisitIdentifierExpression(IdentifierExpression identifierExpression) public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
{ {
if (startLocation.IsEmpty || startLocation <= identifierExpression.StartLocation && identifierExpression.EndLocation <= endLocation) { if (startLocation.IsEmpty || startLocation <= identifierExpression.StartLocation && identifierExpression.EndLocation <= endLocation) {
var result = context.Resolve(identifierExpression) as LocalResolveResult;
if (result != null && usedVariables.Contains (result.Variable))
SetState (identifierExpression.Identifier, VariableState.Used); SetState (identifierExpression.Identifier, VariableState.Used);
} }
} }
@ -103,9 +106,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{ {
if (startLocation.IsEmpty || startLocation <= assignmentExpression.StartLocation && assignmentExpression.EndLocation <= endLocation) { if (startLocation.IsEmpty || startLocation <= assignmentExpression.StartLocation && assignmentExpression.EndLocation <= endLocation) {
var left = assignmentExpression.Left as IdentifierExpression; var left = assignmentExpression.Left as IdentifierExpression;
if (left != null) if (left != null) {
var result = context.Resolve(left) as LocalResolveResult;
if (result != null && usedVariables.Contains (result.Variable))
SetState(left.Identifier, VariableState.Changed); SetState(left.Identifier, VariableState.Changed);
} }
}
base.VisitAssignmentExpression (assignmentExpression); base.VisitAssignmentExpression (assignmentExpression);
} }
@ -113,17 +119,23 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{ {
if (startLocation.IsEmpty || startLocation <= directionExpression.StartLocation && directionExpression.EndLocation <= endLocation) { if (startLocation.IsEmpty || startLocation <= directionExpression.StartLocation && directionExpression.EndLocation <= endLocation) {
var expr = directionExpression.Expression as IdentifierExpression; var expr = directionExpression.Expression as IdentifierExpression;
if (expr != null) if (expr != null) {
var result = context.Resolve(expr) as LocalResolveResult;
if (result != null && usedVariables.Contains (result.Variable))
SetState(expr.Identifier, VariableState.Changed); SetState(expr.Identifier, VariableState.Changed);
} }
}
base.VisitDirectionExpression (directionExpression); base.VisitDirectionExpression (directionExpression);
} }
public override void VisitVariableInitializer(VariableInitializer variableInitializer) public override void VisitVariableInitializer(VariableInitializer variableInitializer)
{ {
if (startLocation.IsEmpty || startLocation <= variableInitializer.StartLocation && variableInitializer.EndLocation <= endLocation) { if (startLocation.IsEmpty || startLocation <= variableInitializer.StartLocation && variableInitializer.EndLocation <= endLocation) {
var result = context.Resolve(variableInitializer) as LocalResolveResult;
if (result != null && usedVariables.Contains (result.Variable)) {
SetState(variableInitializer.Name, variableInitializer.Initializer.IsNull ? VariableState.None : VariableState.Changed); SetState(variableInitializer.Name, variableInitializer.Initializer.IsNull ? VariableState.None : VariableState.Changed);
} }
}
base.VisitVariableInitializer(variableInitializer); base.VisitVariableInitializer(variableInitializer);
} }
@ -134,10 +146,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
if (unaryOperatorExpression.Operator == UnaryOperatorType.Increment || unaryOperatorExpression.Operator == UnaryOperatorType.Decrement || if (unaryOperatorExpression.Operator == UnaryOperatorType.Increment || unaryOperatorExpression.Operator == UnaryOperatorType.Decrement ||
unaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement || unaryOperatorExpression.Operator == UnaryOperatorType.PostDecrement) { unaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement || unaryOperatorExpression.Operator == UnaryOperatorType.PostDecrement) {
var expr = unaryOperatorExpression.Expression as IdentifierExpression; var expr = unaryOperatorExpression.Expression as IdentifierExpression;
if (expr != null) if (expr != null) {
var result = context.Resolve(expr) as LocalResolveResult;
if (result != null && usedVariables.Contains (result.Variable))
SetState(expr.Identifier, VariableState.Changed); SetState(expr.Identifier, VariableState.Changed);
} }
} }
}
base.VisitUnaryOperatorExpression (unaryOperatorExpression); base.VisitUnaryOperatorExpression (unaryOperatorExpression);
} }

72
ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtractMethodTests.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
[TestFixture] [TestFixture]
public class ExtractMethodTests : ContextActionTestBase public class ExtractMethodTests : ContextActionTestBase
{ {
[Test()] [Test]
public void SimpleArgument() public void SimpleArgument()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -56,7 +56,8 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
} }
"); ");
} }
[Test()]
[Test]
public void NoArgument() public void NoArgument()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -82,7 +83,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
"); ");
} }
[Test()] [Test]
public void ExtractMethodResultStatementTest() public void ExtractMethodResultStatementTest()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -112,7 +113,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
"); ");
} }
[Test()] [Test]
public void ExtractMethodResultExpressionTest() public void ExtractMethodResultExpressionTest()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -140,7 +141,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
"); ");
} }
[Test()] [Test]
public void ExtractMethodStaticResultStatementTest() public void ExtractMethodStaticResultStatementTest()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -168,7 +169,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
"); ");
} }
[Test()] [Test]
public void ExtractMethodStaticResultExpressionTest() public void ExtractMethodStaticResultExpressionTest()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -194,7 +195,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
"); ");
} }
[Test()] [Test]
public void ExtractMethodMultiVariableTest() public void ExtractMethodMultiVariableTest()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -229,7 +230,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
/// <summary> /// <summary>
/// Bug 607990 - "Extract Method" refactoring sometimes tries to pass in unnecessary parameter depending on selection /// Bug 607990 - "Extract Method" refactoring sometimes tries to pass in unnecessary parameter depending on selection
/// </summary> /// </summary>
[Test()] [Test]
public void TestBug607990() public void TestBug607990()
{ {
Test<ExtractMethodAction>(@"using System; Test<ExtractMethodAction>(@"using System;
@ -261,7 +262,7 @@ class TestClass
/// <summary> /// <summary>
/// Bug 616193 - Extract method passes param with does not exists any more in main method /// Bug 616193 - Extract method passes param with does not exists any more in main method
/// </summary> /// </summary>
[Test()] [Test]
public void TestBug616193() public void TestBug616193()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -296,7 +297,7 @@ class TestClass
/// <summary> /// <summary>
/// Bug 616199 - Extract method forgets to return a local var which is used in main method /// Bug 616199 - Extract method forgets to return a local var which is used in main method
/// </summary> /// </summary>
[Test()] [Test]
public void TestBug616199() public void TestBug616199()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -326,7 +327,7 @@ class TestClass
/// <summary> /// <summary>
/// Bug 666271 - "Extract Method" on single line adds two semi-colons in method, none in replaced text /// Bug 666271 - "Extract Method" on single line adds two semi-colons in method, none in replaced text
/// </summary> /// </summary>
[Test()] [Test]
public void TestBug666271() public void TestBug666271()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -354,7 +355,7 @@ class TestClass
/// <summary> /// <summary>
/// Bug 693944 - Extracted method returns void instead of the correct type /// Bug 693944 - Extracted method returns void instead of the correct type
/// </summary> /// </summary>
[Test()] [Test]
public void TestBug693944() public void TestBug693944()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -379,7 +380,7 @@ class TestClass
} }
[Ignore("Fix me!")] [Ignore("Fix me!")]
[Test()] [Test]
public void ExtractMethodMultiVariableWithLocalReturnVariableTest() public void ExtractMethodMultiVariableWithLocalReturnVariableTest()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -418,7 +419,7 @@ class TestClass
/// <summary> /// <summary>
/// Bug 8835 - missing "extract method" in the code editor /// Bug 8835 - missing "extract method" in the code editor
/// </summary> /// </summary>
[Test()] [Test]
public void TestBug8835 () public void TestBug8835 ()
{ {
Test<ExtractMethodAction>(@"class TestClass Test<ExtractMethodAction>(@"class TestClass
@ -443,6 +444,49 @@ class TestClass
} }
"); ");
} }
/// <summary>
/// Bug 9881 - Extract method is broken
/// </summary>
[Test]
public void TestBug9881()
{
Test<ExtractMethodAction>(@"using System.Linq;
class TestClass
{
void Foo ()
{
var val = Enumerable.Range (0, 10).ToList ();
<-for (int j = 0; j < val.Count; j++) {
int i = val [j];
Console.WriteLine (i);
}->
foreach (var i in val) {
Console.WriteLine (i + 2);
}
}
}", @"using System.Linq;
class TestClass
{
static void NewMethod (System.Collections.Generic.List<int> val)
{
for (int j = 0; j < val.Count; j++) {
int i = val [j];
Console.WriteLine (i);
}
}
void Foo ()
{
var val = Enumerable.Range (0, 10).ToList ();
NewMethod (val);
foreach (var i in val) {
Console.WriteLine (i + 2);
}
}
}");
}
} }
} }

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

@ -262,6 +262,10 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
var parser = new CSharpParser(); var parser = new CSharpParser();
var unit = parser.Parse(content, "program.cs"); var unit = parser.Parse(content, "program.cs");
if (!expectErrors) { if (!expectErrors) {
if (parser.HasErrors) {
Console.WriteLine (content);
Console.WriteLine ("----");
}
foreach (var error in parser.Errors) { foreach (var error in parser.Errors) {
Console.WriteLine(error.Message); Console.WriteLine(error.Message);
} }

Loading…
Cancel
Save