Skip to content

Commit

Permalink
Fix analyzer RCS1124 - Do not cast if not necessary (#1572)
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt authored Oct 25, 2024
1 parent 55f220e commit 702b9f7
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 10 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

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

### Change
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private static async Task<Document> RefactorAsync(

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

ExpressionSyntax value = GetExpressionToInline(localDeclaration, semanticModel, cancellationToken);
ExpressionSyntax value = GetExpressionToInline(localDeclaration, nextStatement, semanticModel, cancellationToken);

StatementSyntax newStatement = GetStatementWithInlinedExpression(nextStatement, value);

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

private static ExpressionSyntax GetExpressionToInline(LocalDeclarationStatementSyntax localDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken)
private static ExpressionSyntax GetExpressionToInline(
LocalDeclarationStatementSyntax localDeclaration,
StatementSyntax statement,
SemanticModel semanticModel,
CancellationToken cancellationToken)
{
VariableDeclarationSyntax variableDeclaration = localDeclaration.Declaration;

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

ExpressionSyntax typeExpression = (variableDeclaration.Type.IsVar)
? variableDeclaration.Variables[0].Initializer.Value
: variableDeclaration.Type;
TypeSyntax type = variableDeclaration.Type;
ITypeSymbol typeSymbol;

ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(typeExpression, cancellationToken);
if (type.IsVar)
{
typeSymbol = semanticModel.GetTypeSymbol(variableDeclaration.Variables[0].Initializer.Value, cancellationToken)!;
type = typeSymbol.ToTypeSyntax().WithSimplifierAnnotation();
}
else
{
typeSymbol = semanticModel.GetTypeSymbol(type, cancellationToken)!;
}

if (typeSymbol.SupportsExplicitDeclaration())
bool ShouldAddCast()
{
TypeSyntax type = typeSymbol.ToMinimalTypeSyntax(semanticModel, localDeclaration.SpanStart);
if (!typeSymbol.SupportsExplicitDeclaration())
return false;

if (statement.IsKind(SyntaxKind.ReturnStatement))
{
IMethodSymbol enclosingSymbol = semanticModel.GetEnclosingSymbol<IMethodSymbol>(variableDeclaration.Type.SpanStart, cancellationToken);

if (enclosingSymbol is not null
&& SymbolEqualityComparer.Default.Equals(typeSymbol, enclosingSymbol.ReturnType))
{
return false;
}
}

expression = SyntaxFactory.CastExpression(type, expression).WithSimplifierAnnotation();
return true;
}

return expression;
return (ShouldAddCast())
? SyntaxFactory.CastExpression(type.WithoutTrivia(), expression).WithSimplifierAnnotation()
: expression;
}
}

Expand Down
27 changes: 27 additions & 0 deletions src/Tests/Analyzers.Tests/RCS1124InlineLocalVariableTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,33 @@ void M()
");
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.InlineLocalVariable)]
public async Task Test_NullableReturnType_ReturnsNullable()
{
await VerifyDiagnosticAndFixAsync(@"
public struct S;
public class C
{
public static S? M()
{
[|S? i = new S();|]
return i;
}
}
", @"
public struct S;
public class C
{
public static S? M()
{
return new S();
}
}
");
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.InlineLocalVariable)]
public async Task TestNoDiagnostic_YieldReturnIsNotLastStatement()
{
Expand Down

0 comments on commit 702b9f7

Please sign in to comment.