Skip to content

Commit

Permalink
Put back refactoring RR0194 (fix #881)
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt committed Mar 13, 2022
1 parent a61fb2a commit 9ed14ad
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 4 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Expand Up @@ -7,6 +7,7 @@
* Call AddRange instead of Add (RCS1235)
* Add code fix for CS8602, CS8604
* Fix code fix for CS0225
* Put back refactoring SplitLocalDeclarationAndAssignment (RR0194) ([issue](https://github.com/JosefPihrt/Roslynator/issues/881))

### 4.0.3 (2022-01-29)

Expand Down
1 change: 1 addition & 0 deletions docs/Configuration.md
Expand Up @@ -1133,6 +1133,7 @@ roslynator_refactoring.sort_member_declarations.enabled = true
roslynator_refactoring.split_attributes.enabled = true
roslynator_refactoring.split_if.enabled = true
roslynator_refactoring.split_if_else.enabled = true
roslynator_refactoring.split_local_declaration_and_assignment.enabled = true
roslynator_refactoring.split_switch_labels.enabled = true
roslynator_refactoring.split_variable_declaration.enabled = true
roslynator_refactoring.swap_binary_operands.enabled = true
Expand Down
Expand Up @@ -170,6 +170,7 @@ public static class RefactoringDescriptors
public static RefactoringDescriptor SplitAttributes = new RefactoringDescriptor("RR0156", "roslynator_refactoring.split_attributes.enabled", isEnabledByDefault: true);
public static RefactoringDescriptor SplitIf = new RefactoringDescriptor("RR0184", "roslynator_refactoring.split_if.enabled", isEnabledByDefault: true);
public static RefactoringDescriptor SplitIfElse = new RefactoringDescriptor("RR0190", "roslynator_refactoring.split_if_else.enabled", isEnabledByDefault: true);
public static RefactoringDescriptor SplitLocalDeclarationAndAssignment = new RefactoringDescriptor("RR0194", "roslynator_refactoring.split_local_declaration_and_assignment.enabled", isEnabledByDefault: true);
public static RefactoringDescriptor SplitSwitchLabels = new RefactoringDescriptor("RR0157", "roslynator_refactoring.split_switch_labels.enabled", isEnabledByDefault: true);
public static RefactoringDescriptor SplitVariableDeclaration = new RefactoringDescriptor("RR0158", "roslynator_refactoring.split_variable_declaration.enabled", isEnabledByDefault: true);
public static RefactoringDescriptor SwapBinaryOperands = new RefactoringDescriptor("RR0159", "roslynator_refactoring.swap_binary_operands.enabled", isEnabledByDefault: true);
Expand Down
Expand Up @@ -31,8 +31,6 @@ public static partial class RefactoringIdentifiers
[Obsolete("", error: false)]
public const string MergeInterpolationIntoInterpolatedString = Prefix + "0076";
[Obsolete("", error: false)]
public const string SplitDeclarationAndInitialization = Prefix + "0194";
[Obsolete("", error: false)]
public const string UseEmptyStringLiteralInsteadOfStringEmpty = Prefix + "0168";
[Obsolete("", error: false)]
public const string WrapInElseClause = Prefix + "0173";
Expand Down
Expand Up @@ -172,6 +172,7 @@ public static partial class RefactoringIdentifiers
public const string SplitAttributes = Prefix + "0156";
public const string SplitIf = Prefix + "0184";
public const string SplitIfElse = Prefix + "0190";
public const string SplitLocalDeclarationAndAssignment = Prefix + "0194";
public const string SplitSwitchLabels = Prefix + "0157";
public const string SplitVariableDeclaration = Prefix + "0158";
public const string SwapBinaryOperands = Prefix + "0159";
Expand Down
Expand Up @@ -21,6 +21,9 @@ public static async Task ComputeRefactoringsAsync(RefactoringContext context, Lo

if (context.IsRefactoringEnabled(RefactoringDescriptors.RemoveInstantiationOfLocalVariable))
await RemoveInstantiationOfLocalVariableRefactoring.ComputeRefactoringAsync(context, localDeclaration).ConfigureAwait(false);

if (context.IsRefactoringEnabled(RefactoringDescriptors.SplitLocalDeclarationAndAssignment))
await SplitLocalDeclarationAndAssignmentRefactoring.ComputeRefactoringAsync(context, localDeclaration).ConfigureAwait(false);
}
}
}
@@ -0,0 +1,104 @@
// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslynator.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using static Roslynator.CSharp.CSharpFactory;

namespace Roslynator.CSharp.Refactorings
{
internal static class SplitLocalDeclarationAndAssignmentRefactoring
{
public static async Task ComputeRefactoringAsync(
RefactoringContext context,
LocalDeclarationStatementSyntax localDeclaration)
{
StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(localDeclaration);

if (!statementsInfo.Success)
return;

SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

if (!localInfo.Success)
return;

if (!context.Span.IsEmpty
&& context.Span.Start == localInfo.EqualsToken.SpanStart)
{
return;
}

ExpressionSyntax value = localInfo.Value;

if (value == null)
return;

SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

TypeSyntax type = localInfo.Type;

if (type.IsVar)
{
ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(value, context.CancellationToken);

if (typeSymbol?.SupportsExplicitDeclaration() != true)
return;

type = typeSymbol.ToMinimalTypeSyntax(semanticModel, type.SpanStart);
}
else
{
ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken);

if (typeSymbol?.IsErrorType() != false)
return;
}

context.RegisterRefactoring(
"Split declaration and assignment",
ct => RefactorAsync(context.Document, localInfo, type, statementsInfo, ct),
RefactoringDescriptors.SplitLocalDeclarationAndAssignment);
}

private static Task<Document> RefactorAsync(
Document document,
in SingleLocalDeclarationStatementInfo localInfo,
TypeSyntax type,
in StatementListInfo statementsInfo,
CancellationToken cancellationToken)
{
LocalDeclarationStatementSyntax localStatement = localInfo.Statement;

int index = statementsInfo.IndexOf(localStatement);

VariableDeclaratorSyntax declarator = localInfo.Declarator;

VariableDeclaratorSyntax newDeclarator = declarator.WithInitializer(null);

VariableDeclarationSyntax newDeclaration = localInfo.Declaration.ReplaceNode(declarator, newDeclarator);

if (type != null)
newDeclaration = newDeclaration.WithType(type.WithTriviaFrom(newDeclaration.Type));

LocalDeclarationStatementSyntax newLocalStatement = localStatement
.WithDeclaration(newDeclaration)
.WithSemicolonToken(localStatement.SemicolonToken.WithNavigationAnnotation())
.WithTrailingTrivia(NewLine())
.WithFormatterAnnotation();

ExpressionStatementSyntax assignmentStatement = SimpleAssignmentStatement(IdentifierName(localInfo.Identifier), localInfo.Initializer.Value)
.WithTrailingTrivia(localStatement.GetTrailingTrivia())
.WithFormatterAnnotation();

StatementListInfo newStatementsInfo = statementsInfo
.Insert(index + 1, assignmentStatement)
.ReplaceAt(index, newLocalStatement);

return document.ReplaceStatementsAsync(statementsInfo, newStatementsInfo, cancellationToken);
}
}
}
5 changes: 3 additions & 2 deletions src/Refactorings/Refactorings.xml
Expand Up @@ -1892,8 +1892,9 @@ public class Foo
</Sample>
</Samples>
</Refactoring>
<Refactoring Id="RR0194" Identifier="SplitDeclarationAndInitialization" Title="Split declaration and initialization" IsObsolete="true">
<Syntaxes>
<Refactoring Id="RR0194" Identifier="SplitLocalDeclarationAndAssignment" Title="Split local declaration and assignment">
<OptionKey>split_local_declaration_and_assignment</OptionKey>
<Syntaxes>
<Syntax>local variable declaration</Syntax>
</Syntaxes>
<Span>equals token</Span>
Expand Down
@@ -0,0 +1,36 @@
// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Threading.Tasks;
using Roslynator.Testing.CSharp;
using Xunit;

namespace Roslynator.CSharp.Refactorings.Tests
{
public class RR0194SplitLocalDeclarationAndAssignmentTests : AbstractCSharpRefactoringVerifier
{
public override string RefactoringId { get; } = RefactoringIdentifiers.SplitLocalDeclarationAndAssignment;

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.SplitLocalDeclarationAndAssignment)]
public async Task TestRefactoring()
{
await VerifyRefactoringAsync(@"
class C
{
void M()
{
string s [||]= new string(' ', 1);
}
}
", @"
class C
{
void M()
{
string s;
s = new string(' ', 1);
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}
}
}
Expand Up @@ -1105,6 +1105,7 @@ roslynator_analyzers.enabled_by_default = true|false
#roslynator_refactoring.split_attributes.enabled = true
#roslynator_refactoring.split_if.enabled = true
#roslynator_refactoring.split_if_else.enabled = true
#roslynator_refactoring.split_local_declaration_and_assignment.enabled = true
#roslynator_refactoring.split_switch_labels.enabled = true
#roslynator_refactoring.split_variable_declaration.enabled = true
#roslynator_refactoring.swap_binary_operands.enabled = true
Expand Down

0 comments on commit 9ed14ad

Please sign in to comment.