Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infer better variable name when initializing from an anonymous type #76145

Merged
merged 2 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings.IntroduceVariable;

[Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)]
public class IntroduceVariableTests : AbstractCSharpCodeActionTest_NoEditor
public sealed class IntroduceVariableTests : AbstractCSharpCodeActionTest_NoEditor
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(TestWorkspace workspace, TestParameters parameters)
=> new IntroduceVariableCodeRefactoringProvider();
Expand Down Expand Up @@ -6245,11 +6245,11 @@ namespace C
{
class C
{
private const int {|Rename:V|} = 1 + 1;
private const int {|Rename:foo|} = 1 + 1;

void M()
{
var t = new { foo = V };
var t = new { foo = foo };
}
}
}
Expand Down Expand Up @@ -8984,4 +8984,33 @@ public class C
}
""");
}

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21602")]
public async Task DetermineNameFromAnonymousObjectMember()
{
await TestInRegularAndScriptAsync(
"""
using System;

class C
{
void M()
{
var x = new { y = [|DateTime.Now.ToString()|] };
}
}
""",
"""
using System;

class C
{
void M()
{
string {|Rename:y|} = DateTime.Now.ToString();
var x = new { y = y };
}
}
""");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -362,44 +362,48 @@ public static string GenerateNameForExpression(
current = current.WalkDownParentheses();

if (current is IdentifierNameSyntax identifierName)
{
return identifierName.Identifier.ValueText.ToCamelCase();
}
else if (current is MemberAccessExpressionSyntax memberAccess)
{

if (current is MemberAccessExpressionSyntax memberAccess)
return memberAccess.Name.Identifier.ValueText.ToCamelCase();
}
else if (current is MemberBindingExpressionSyntax memberBinding)
{

if (current is MemberBindingExpressionSyntax memberBinding)
return memberBinding.Name.Identifier.ValueText.ToCamelCase();
}
else if (current is ConditionalAccessExpressionSyntax conditionalAccess)
{
current = conditionalAccess.WhenNotNull;
}
else if (current is CastExpressionSyntax castExpression)
{
current = castExpression.Expression;
}
else if (current is DeclarationExpressionSyntax decl)

if (current is DeclarationExpressionSyntax decl)
{
if (decl.Designation is not SingleVariableDesignationSyntax name)
{
break;
}

return name.Identifier.ValueText.ToCamelCase();
}
else if (current.Parent is ForEachStatementSyntax foreachStatement &&
foreachStatement.Expression == expression)

if (current.Parent is ForEachStatementSyntax foreachStatement &&
foreachStatement.Expression == expression)
{
var word = foreachStatement.Identifier.ValueText.ToCamelCase();
return CodeAnalysis.Shared.Extensions.SemanticModelExtensions.Pluralize(word);
}
else

if (current.Parent is AnonymousObjectMemberDeclaratorSyntax { NameEquals: { } nameEquals } anonymousObjectMemberDeclarator &&
anonymousObjectMemberDeclarator.Expression == current)
{
break;
return nameEquals.Name.Identifier.ValueText.ToCamelCase();
}

if (current is ConditionalAccessExpressionSyntax conditionalAccess)
{
current = conditionalAccess.WhenNotNull;
continue;
}

if (current is CastExpressionSyntax castExpression)
{
current = castExpression.Expression;
continue;
}

break;
}

// there was nothing in the expression to signify a name. If we're in an argument
Expand Down
Loading