Skip to content

Commit 702b9f7

Browse files
authored
Fix analyzer RCS1124 - Do not cast if not necessary (#1572)
1 parent 55f220e commit 702b9f7

File tree

3 files changed

+63
-10
lines changed

3 files changed

+63
-10
lines changed

ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Fixed
1111

1212
- Fix analyzer [RCS1090](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1090) ([PR](https://github.com/dotnet/roslynator/pull/1566))
13+
- Fix analyzer [RCS1124](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1124) ([PR](https://github.com/dotnet/roslynator/pull/1572))
1314
- [CLI] Fix command `generate-doc` ([PR](https://github.com/dotnet/roslynator/pull/1568), [PR](https://github.com/dotnet/roslynator/pull/1570))
1415

1516
### Change

src/Analyzers.CodeFixes/CSharp/CodeFixes/LocalDeclarationStatementCodeFixProvider.cs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ private static async Task<Document> RefactorAsync(
6767

6868
SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
6969

70-
ExpressionSyntax value = GetExpressionToInline(localDeclaration, semanticModel, cancellationToken);
70+
ExpressionSyntax value = GetExpressionToInline(localDeclaration, nextStatement, semanticModel, cancellationToken);
7171

7272
StatementSyntax newStatement = GetStatementWithInlinedExpression(nextStatement, value);
7373

@@ -93,7 +93,11 @@ private static async Task<Document> RefactorAsync(
9393
return await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false);
9494
}
9595

96-
private static ExpressionSyntax GetExpressionToInline(LocalDeclarationStatementSyntax localDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken)
96+
private static ExpressionSyntax GetExpressionToInline(
97+
LocalDeclarationStatementSyntax localDeclaration,
98+
StatementSyntax statement,
99+
SemanticModel semanticModel,
100+
CancellationToken cancellationToken)
97101
{
98102
VariableDeclarationSyntax variableDeclaration = localDeclaration.Declaration;
99103

@@ -114,20 +118,41 @@ private static ExpressionSyntax GetExpressionToInline(LocalDeclarationStatementS
114118
{
115119
expression = expression.Parenthesize();
116120

117-
ExpressionSyntax typeExpression = (variableDeclaration.Type.IsVar)
118-
? variableDeclaration.Variables[0].Initializer.Value
119-
: variableDeclaration.Type;
121+
TypeSyntax type = variableDeclaration.Type;
122+
ITypeSymbol typeSymbol;
120123

121-
ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(typeExpression, cancellationToken);
124+
if (type.IsVar)
125+
{
126+
typeSymbol = semanticModel.GetTypeSymbol(variableDeclaration.Variables[0].Initializer.Value, cancellationToken)!;
127+
type = typeSymbol.ToTypeSyntax().WithSimplifierAnnotation();
128+
}
129+
else
130+
{
131+
typeSymbol = semanticModel.GetTypeSymbol(type, cancellationToken)!;
132+
}
122133

123-
if (typeSymbol.SupportsExplicitDeclaration())
134+
bool ShouldAddCast()
124135
{
125-
TypeSyntax type = typeSymbol.ToMinimalTypeSyntax(semanticModel, localDeclaration.SpanStart);
136+
if (!typeSymbol.SupportsExplicitDeclaration())
137+
return false;
138+
139+
if (statement.IsKind(SyntaxKind.ReturnStatement))
140+
{
141+
IMethodSymbol enclosingSymbol = semanticModel.GetEnclosingSymbol<IMethodSymbol>(variableDeclaration.Type.SpanStart, cancellationToken);
142+
143+
if (enclosingSymbol is not null
144+
&& SymbolEqualityComparer.Default.Equals(typeSymbol, enclosingSymbol.ReturnType))
145+
{
146+
return false;
147+
}
148+
}
126149

127-
expression = SyntaxFactory.CastExpression(type, expression).WithSimplifierAnnotation();
150+
return true;
128151
}
129152

130-
return expression;
153+
return (ShouldAddCast())
154+
? SyntaxFactory.CastExpression(type.WithoutTrivia(), expression).WithSimplifierAnnotation()
155+
: expression;
131156
}
132157
}
133158

src/Tests/Analyzers.Tests/RCS1124InlineLocalVariableTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,33 @@ void M()
101101
");
102102
}
103103

104+
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.InlineLocalVariable)]
105+
public async Task Test_NullableReturnType_ReturnsNullable()
106+
{
107+
await VerifyDiagnosticAndFixAsync(@"
108+
public struct S;
109+
110+
public class C
111+
{
112+
public static S? M()
113+
{
114+
[|S? i = new S();|]
115+
return i;
116+
}
117+
}
118+
", @"
119+
public struct S;
120+
121+
public class C
122+
{
123+
public static S? M()
124+
{
125+
return new S();
126+
}
127+
}
128+
");
129+
}
130+
104131
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.InlineLocalVariable)]
105132
public async Task TestNoDiagnostic_YieldReturnIsNotLastStatement()
106133
{

0 commit comments

Comments
 (0)