diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs index eedf4add2f10896e4c3205c28b6337994c49f99d..7863441ba4d869af5424471994abafac56df1eca 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs @@ -41,7 +41,7 @@ protected override SyntaxToken CreateMethodName(bool localFunction) var semanticModel = this.SemanticDocument.SemanticModel; var nameGenerator = new UniqueNameGenerator(semanticModel); - return SyntaxFactory.Identifier(nameGenerator.CreateUniqueMethodName(containingScope, methodName, localFunction)); + return SyntaxFactory.Identifier(nameGenerator.CreateUniqueMethodName(containingScope, methodName)); } private static string GetMethodNameBasedOnExpression(string methodName, SyntaxNode expression) diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs index 06a22a6db99554dec5e030dfd48dc6a6d648f96a..a9843d1b50f9509406f27ae4ba0beacb4303e1a2 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs @@ -47,7 +47,14 @@ protected override SyntaxToken CreateMethodName(bool localFunction) var semanticModel = this.SemanticDocument.SemanticModel; var nameGenerator = new UniqueNameGenerator(semanticModel); var scope = this.CSharpSelectionResult.GetContainingScope(); - return SyntaxFactory.Identifier(nameGenerator.CreateUniqueMethodName(scope, "NewMethod", localFunction)); + + // If extracting a local function, we want to ensure all local variables are considered when generating a unique name. + if (localFunction) + { + scope = this.CSharpSelectionResult.GetFirstTokenInSelection().Parent; + } + + return SyntaxFactory.Identifier(nameGenerator.CreateUniqueMethodName(scope, "NewMethod")); } protected override IEnumerable GetInitialStatementsForMethodDefinitions() diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs index 4c4f875d6f257733dc0043aab1a3f778a9d554d9..63470a6effebb70a04e26d4f81d08bf9339e1425 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs @@ -39,7 +39,14 @@ protected override SyntaxToken CreateMethodName(bool localFunction) var semanticModel = this.SemanticDocument.SemanticModel; var nameGenerator = new UniqueNameGenerator(semanticModel); var scope = this.CSharpSelectionResult.GetContainingScope(); - return SyntaxFactory.Identifier(nameGenerator.CreateUniqueMethodName(scope, "NewMethod", localFunction)); + + // If extracting a local function, we want to ensure all local variables are considered when generating a unique name. + if (localFunction) + { + scope = this.CSharpSelectionResult.GetFirstTokenInSelection().Parent; + } + + return SyntaxFactory.Identifier(nameGenerator.CreateUniqueMethodName(scope, "NewMethod")); } protected override IEnumerable GetInitialStatementsForMethodDefinitions() diff --git a/src/Features/Core/Portable/ExtractMethod/UniqueNameGenerator.cs b/src/Features/Core/Portable/ExtractMethod/UniqueNameGenerator.cs index 6c8ac9ae0294ec4d3a3bd68a9f37d12bf5e857de..f26219af1d3e7d42ce81b053f1a0adb307b1a6b3 100644 --- a/src/Features/Core/Portable/ExtractMethod/UniqueNameGenerator.cs +++ b/src/Features/Core/Portable/ExtractMethod/UniqueNameGenerator.cs @@ -16,23 +16,11 @@ public UniqueNameGenerator(SemanticModel semanticModel) _semanticModel = semanticModel; } - public string CreateUniqueMethodName(SyntaxNode contextNode, string baseName, bool localFunction = false) + public string CreateUniqueMethodName(SyntaxNode contextNode, string baseName) { Contract.ThrowIfNull(contextNode); Contract.ThrowIfNull(baseName); - if (localFunction) - { - // When generating local functions, we also want to take into account the names of local variables. - var childNodes = contextNode.ChildNodes().AsArray(); - if (childNodes.Length > 0) - { - // If we take the first child node, we may end up with part of the method header. - // To be safe, we use the last child node, which is guaranteed to be part of the context method's body. - contextNode = (SyntaxNode)childNodes.GetValue(childNodes.Length - 1); - } - } - return NameGenerator.GenerateUniqueName(baseName, string.Empty, n => _semanticModel.LookupSymbols(contextNode.SpanStart, container: null, n).Length == 0); }