diff --git a/ChangeLog.md b/ChangeLog.md index 472c375eb9..5d31ab20f7 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix analyzer [RCS0049](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0049) ([PR](https://github.com/dotnet/roslynator/pull/1386)) - Fix analyzer [RCS1159](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1159) ([PR](https://github.com/dotnet/roslynator/pull/1390)) +- Fix code fix for [CS8600](https://josefpihrt.github.io/docs/roslynator/fixes/CS8600) changing the wrong type when casts or `var` are involved ([PR](https://github.com/dotnet/roslynator/pull/1393)) ## [4.10.0] - 2024-01-24 diff --git a/src/CodeFixes/CSharp/CodeFixes/DeclareAsNullableCodeFixProvider.cs b/src/CodeFixes/CSharp/CodeFixes/DeclareAsNullableCodeFixProvider.cs index 25da08b3bb..4601a24436 100644 --- a/src/CodeFixes/CSharp/CodeFixes/DeclareAsNullableCodeFixProvider.cs +++ b/src/CodeFixes/CSharp/CodeFixes/DeclareAsNullableCodeFixProvider.cs @@ -101,28 +101,31 @@ private static void TryRegisterCodeFixForCast(CodeFixContext context, Diagnostic async ct => { NullableTypeSyntax newType = SyntaxFactory.NullableType(type.WithoutTrivia()).WithTriviaFrom(type); - Document changedDocument = await context.Document.ReplaceNodeAsync(type, newType, ct).ConfigureAwait(false); - // This could be in a variable declaration, so grab the new syntax root and find the newly-replaced type node - SyntaxNode root = await changedDocument.GetSyntaxRootAsync(ct).ConfigureAwait(false); - SyntaxNode insertedNewType = root.FindNode(type.Span); - - // Try finding a surrounding variable declaration whose type we also have to change - if (insertedNewType.AncestorsAndSelf().FirstOrDefault(a => a.IsKind(SyntaxKind.EqualsValueClause)) is EqualsValueClauseSyntax equalsValueClause) - { - ExpressionSyntax expression = equalsValueClause.Value; - - if (equalsValueClause.IsParentKind(SyntaxKind.VariableDeclarator) - && equalsValueClause.Parent.Parent is VariableDeclarationSyntax variableDeclaration - && variableDeclaration.Variables.Count == 1 - && !variableDeclaration.Type.IsKind(SyntaxKind.NullableType) - && variableDeclaration.Type is not IdentifierNameSyntax { Identifier.Text: "var" }) + // This could be in a variable declaration whose type we also may have to change + if (type.Parent?.Parent is EqualsValueClauseSyntax { - NullableTypeSyntax newDeclarationType = SyntaxFactory.NullableType(variableDeclaration.Type.WithoutTrivia()).WithTriviaFrom(variableDeclaration.Type); - changedDocument = await changedDocument.ReplaceNodeAsync(variableDeclaration.Type, newDeclarationType, ct).ConfigureAwait(false); + Parent: VariableDeclaratorSyntax + { + Parent: VariableDeclarationSyntax + { + Variables.Count: 1, + Type: { IsVar: false } declarationType + } variableDeclaration + } } + && !declarationType.IsKind(SyntaxKind.NullableType)) + { + NullableTypeSyntax newDeclarationType = SyntaxFactory.NullableType(declarationType.WithoutTrivia()).WithTriviaFrom(declarationType); + VariableDeclarationSyntax newVariableDeclaration = variableDeclaration + .ReplaceNode(type, newType) + .WithType(newDeclarationType); + return await context.Document.ReplaceNodeAsync(variableDeclaration, newVariableDeclaration, ct).ConfigureAwait(false); + } + else + { + return await context.Document.ReplaceNodeAsync(type, newType, ct).ConfigureAwait(false); } - return changedDocument; }, GetEquivalenceKey(diagnostic));