// // AccessToModifiedClosureTests.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.CodeActions; using ICSharpCode.NRefactory.CSharp.Refactoring; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.CodeIssues { [TestFixture] public class AccessToModifiedClosureTests : InspectionActionTestBase { static void Test(string input, int issueCount, string output = null, int fixIndex = -1) { TestRefactoringContext context; var issues = GetIssues (new AccessToModifiedClosureIssue (), input, out context); Assert.AreEqual (issueCount, issues.Count); if (issueCount > 0) { if (output != null) { if (fixIndex == -1) CheckFix (context, issues, output); else CheckFix (context, issues [fixIndex], output); } else { foreach (var issue in issues) Assert.AreEqual (0, issue.Actions.Count); } } } [Test] public void TestForeachVariable () { var input = @" class TestClass { void TestMethod (int[] a) { System.Func f; foreach (var i in a) f = new System.Func (x => x + i); } }"; var output = @" class TestClass { void TestMethod (int[] a) { System.Func f; foreach (var i in a) { var i1 = i; f = new System.Func (x => x + i1); } } }"; Test (input, 1, output); } [Test] public void TestFor () { var input = @" class TestClass { void TestMethod () { for (int i = 0; i < 10; i++) { var f = new System.Func (x => x + i); } } }"; var output = @" class TestClass { void TestMethod () { for (int i = 0; i < 10; i++) { var i1 = i; var f = new System.Func (x => x + i1); } } }"; Test (input, 1, output); } [Test] public void TestForInitializer () { var input = @" class TestClass { void TestMethod (int j) { int i; for (i = 0; j < 10; j++) { var f = new System.Func (x => x + i); } } }"; Test (input, 0); } [Test] public void TestForBody () { var input = @" class TestClass { void TestMethod () { for (int i = 0; i < 10;) { var f = new System.Func (delegate (int x) { return x + i; }); i++; } } }"; var output = @" class TestClass { void TestMethod () { for (int i = 0; i < 10;) { var i1 = i; var f = new System.Func (delegate (int x) { return x + i1; }); i++; } } }"; Test (input, 1, output); } [Test] public void TestWhileBody () { var input = @" class TestClass { void TestMethod () { int i = 0; while (i < 10) { i++; var f = new System.Func (x => x + i); } } }"; var output = @" class TestClass { void TestMethod () { int i = 0; while (i < 10) { i++; var i1 = i; var f = new System.Func (x => x + i1); } } }"; Test (input, 1, output); } [Test] public void TestWhileCondition () { var input = @" class TestClass { void TestMethod () { int i = 0; while (i++ < 10) { var f = new System.Func (delegate (int x) { return x + i; }); } } }"; var output = @" class TestClass { void TestMethod () { int i = 0; while (i++ < 10) { var i1 = i; var f = new System.Func (delegate (int x) { return x + i1; }); } } }"; Test (input, 1, output); } [Test] public void TestDoWhileBody () { var input = @" class TestClass { void TestMethod () { int i = 0; do { i += 1; var f = new System.Func (x => x + i); } while (i < 10); } }"; var output = @" class TestClass { void TestMethod () { int i = 0; do { i += 1; var i1 = i; var f = new System.Func (x => x + i1); } while (i < 10); } }"; Test (input, 1, output); } [Test] public void TestDoWhileCondition () { var input = @" class TestClass { void TestMethod () { int i = 0; while (i++ < 10) { var f = new System.Func (x => x + i); } } }"; var output = @" class TestClass { void TestMethod () { int i = 0; while (i++ < 10) { var i1 = i; var f = new System.Func (x => x + i1); } } }"; Test (input, 1, output); } [Test] public void TestMultipleLambdas () { var input = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { var f = new System.Func (x => x + i); var f2 = new System.Func (x => x + i > 10); } } }"; var output = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { var i1 = i; var f = new System.Func (x => x + i1); var i1 = i; var f2 = new System.Func (x => x + i1 > 10); } } }"; Test (input, 2, output); } [Test] public void TestFixAllInLambda () { var input = @" class TestClass { void TestMethod (int[] array) { foreach (var i in array) { var f = new System.Func (x => { int a = i + 1; int b = i + 2; return a + b + i; }); } } }"; var output = @" class TestClass { void TestMethod (int[] array) { foreach (var i in array) { var i1 = i; var f = new System.Func (x => { int a = i1 + 1; int b = i1 + 2; return a + b + i1; }); } } }"; Test (input, 3, output, 0); } [Test] public void TestModifiedInLambda () { var input = @" class TestClass { void TestMethod (int[] array) { foreach (var i in array) { var f = new System.Func (x => { i = 0; int a = i + 1; int b = i + 2; return a + b + i; }); } } }"; Test (input, 0); input = @" class TestClass { void TestMethod (int[] array) { foreach (var i in array) { var f = new System.Func (x => { i++; int a = i + 1; i = 3; int b = i + 2; return a + b + i; }); } } }"; var output = @" class TestClass { void TestMethod (int[] array) { foreach (var i in array) { var i1 = i; var f = new System.Func (x => { i1++; int a = i1 + 1; i1 = 3; int b = i1 + 2; return a + b + i1; }); } } }"; Test (input, 1, output); } [Test] public void TestNestedLambda () { var input = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { var f = new System.Func (x => { var f2 = new System.Func (y => y - i); return f2 (x) + i; }); } } }"; var output1 = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { var i1 = i; var f = new System.Func (x => { var f2 = new System.Func (y => y - i1); return f2 (x) + i1; }); } } }"; Test (input, 2, output1, 1); var output2 = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { var f = new System.Func (x => { var i1 = i; var f2 = new System.Func (y => y - i1); return f2 (x) + i; }); } } }"; Test (input, 2, output2, 0); } [Test] public void TestMultipleVariables () { var input = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { foreach (var j in a) { var f = new System.Func (x => x + i + j); } } } }"; var output = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { foreach (var j in a) { var i1 = i; var j1 = j; var f = new System.Func (x => x + i1 + j1); } } } }"; Test (input, 2, output); } [Test] public void TestModificationAfterLambdaDecl () { var input = @" class TestClass { void TestMethod () { int i = 0; System.Func f = x => i + x; i += 1; } }"; var output = @" class TestClass { void TestMethod () { int i = 0; var i1 = i; System.Func f = x => i1 + x; i += 1; } }"; Test (input, 1, output); } [Test] public void TestModificationBeforeLambdaDecl () { var input = @" class TestClass { void TestMethod () { int i = 0; i += 1; System.Func f = x => i + x; } }"; Test (input, 0); } [Test] public void TestUnreachable () { var returnCase = @" class TestClass { void TestMethod () { int i = 0; System.Func f = x => i + x; return; i += 1; } }"; var ifCase = @" class TestClass { void TestMethod () { int i = 0; System.Func f; if (i > 0) f = x => i + x; else i += 1; } }"; Test (returnCase, 0); Test (ifCase, 0); } [Test] public void TestParameter () { var input = @" class TestClass { void TestMethod (int i) { System.Func f = x => i + x; i += 1; } }"; var output = @" class TestClass { void TestMethod (int i) { var i1 = i; System.Func f = x => i1 + x; i += 1; } }"; Test (input, 1, output); } [Test] public void TestModificationInSameStatement () { var input1 = @" class TestClass { void TestMethod2 (int b, System.Func a) { TestMethod2 (b++, c => c + b); } }"; var input2 = @" class TestClass { void TestMethod3 (System.Func a, int b) { TestMethod3 (c => c + b, b++); } }"; var output2 = @" class TestClass { void TestMethod3 (System.Func a, int b) { var b1 = b; TestMethod3 (c => c + b1, b++); } }"; Test (input1, 0); Test (input2, 1, output2); } [Test] public void TestInsertion () { var input1 = @" class TestClass { void TestMethod () { int i = 0; System.Func f = null; if ((f = x => x + i) != null) i++; } }"; var output1 = @" class TestClass { void TestMethod () { int i = 0; System.Func f = null; var i1 = i; if ((f = x => x + i1) != null) i++; } }"; Test (input1, 1, output1); var input2 = @" class TestClass { void TestMethod (int k) { int i = 0; System.Func f = null; switch (k) { default: f = x => x + i; break; } i++; } }"; var output2 = @" class TestClass { void TestMethod (int k) { int i = 0; System.Func f = null; switch (k) { default: var i1 = i; f = x => x + i1; break; } i++; } }"; Test (input2, 1, output2); } [Test] public void TestLambdaInLoopCondition () { var forCase = @" class TestClass { void TestMethod () { System.Func f = null; for (int i = 0; i < 10 && ((f = x => x + i) != null); i++) { } } }"; var whileCase = @" class TestClass { void TestMethod () { System.Func f = null; int i = 0; while (i < 10 && (f = x => x + i) != null) i++; } }"; var doWhileCase = @" class TestClass { void TestMethod () { System.Func f = null; int i = 0; do { i++; } while (i < 10 && (f = x => x + i) != null); } }"; Test (forCase, 1); Test (whileCase, 1); Test (doWhileCase, 1); } [Test] public void TestLambdaInForIterator () { var input = @" class TestClass { void TestMethod () { System.Func f = null; for (int i = 0; i < 10; i++, f = x => x + i) { } } }"; Test (input, 1); } [Test] public void TestExistingVariableName () { var input = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { int i1; var f = new System.Func (x => x + i); } } }"; var output = @" class TestClass { void TestMethod (int[] a) { foreach (var i in a) { int i1; var i2 = i; var f = new System.Func (x => x + i2); } } }"; Test (input, 1, output); } [Test] public void TestConstructor () { var input = @" class TestClass { public TestClass (int[] a) { foreach (var i in a) { int i1; var f = new System.Func (x => x + i); } } }"; var output = @" class TestClass { public TestClass (int[] a) { foreach (var i in a) { int i1; var i2 = i; var f = new System.Func (x => x + i2); } } }"; Test (input, 1, output); } [Test] public void TestField () { var input = @" class TestClass { System.Action a = i => { System.Func f = () => i + 1; i++; }; }"; var output = @" class TestClass { System.Action a = i => { var i1 = i; System.Func f = () => i1 + 1; i++; }; }"; Test (input, 1, output); } } }