From 0a0d094ccb32cd1dd10f9bd911cf037a2accc6ba Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Mon, 7 Oct 2024 21:24:05 +0200 Subject: [PATCH] Fix analyzer RCS1223 - handle type declaration with no braces (#1552) --- ChangeLog.md | 1 + ...rkTypeWithDebuggerDisplayAttributeTests.cs | 25 +++++++++++++++++++ ...WithDebuggerDisplayAttributeRefactoring.cs | 22 +++++++++++++--- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index c59f50b615..237df80c85 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fix analyzer [RCS0053](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0053) ([PR](https://github.com/dotnet/roslynator/pull/1547)) +- Fix analyzer [RCS1223](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1223) ([PR](https://github.com/dotnet/roslynator/pull/1552)) ## [4.12.7] - 2024-10-01 diff --git a/src/Tests/Analyzers.Tests/RCS1223MarkTypeWithDebuggerDisplayAttributeTests.cs b/src/Tests/Analyzers.Tests/RCS1223MarkTypeWithDebuggerDisplayAttributeTests.cs index 0ffea94978..61f147947f 100644 --- a/src/Tests/Analyzers.Tests/RCS1223MarkTypeWithDebuggerDisplayAttributeTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1223MarkTypeWithDebuggerDisplayAttributeTests.cs @@ -312,6 +312,31 @@ private string DebuggerDisplay } } } +"""); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.MarkTypeWithDebuggerDisplayAttribute)] + public async Task Test_PublicReadOnlyRefStruct() + { + await VerifyDiagnosticAndFixAsync(""" +using System.Diagnostics; + +public readonly ref struct [|Dummy|]; +""", """ +using System.Diagnostics; + +[DebuggerDisplay("{DebuggerDisplay,nq}")] +public readonly ref struct Dummy +{ + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private string DebuggerDisplay + { + get + { + return ""; + } + } +} """); } } diff --git a/src/Workspaces.Common/CSharp/Refactorings/MarkTypeWithDebuggerDisplayAttributeRefactoring.cs b/src/Workspaces.Common/CSharp/Refactorings/MarkTypeWithDebuggerDisplayAttributeRefactoring.cs index 9ba52cd442..5af855e2ee 100644 --- a/src/Workspaces.Common/CSharp/Refactorings/MarkTypeWithDebuggerDisplayAttributeRefactoring.cs +++ b/src/Workspaces.Common/CSharp/Refactorings/MarkTypeWithDebuggerDisplayAttributeRefactoring.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using static Roslynator.CSharp.CSharpFactory; @@ -16,7 +17,16 @@ public static async Task RefactorAsync( TypeDeclarationSyntax typeDeclaration, CancellationToken cancellationToken) { - int position = typeDeclaration.OpenBraceToken.Span.End; + TypeDeclarationSyntax newTypeDeclaration = typeDeclaration; + + if (typeDeclaration.OpenBraceToken.IsKind(SyntaxKind.None)) + { + newTypeDeclaration = typeDeclaration.WithSemicolonToken(default) + .WithOpenBraceToken(OpenBraceToken()) + .WithCloseBraceToken(CloseBraceToken()); + } + + int position = newTypeDeclaration.Identifier.Span.End; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); @@ -27,9 +37,15 @@ public static async Task RefactorAsync( ParseName("System.Diagnostics.DebuggerDisplayAttribute").WithSimplifierAnnotation(), AttributeArgument(LiteralExpression($"{{{propertyName},nq}}")))); - PropertyDeclarationSyntax propertyDeclaration = DebuggerDisplayPropertyDeclaration(propertyName, InvocationExpression(IdentifierName("ToString"))); + INamedTypeSymbol typeSymbol = semanticModel.GetDeclaredSymbol(typeDeclaration, cancellationToken)!; + + ExpressionSyntax returnExpression = (typeSymbol.TypeKind == TypeKind.Struct && typeSymbol.IsRefLikeType) + ? StringLiteralExpression("") + : InvocationExpression(IdentifierName("ToString")); + + PropertyDeclarationSyntax propertyDeclaration = DebuggerDisplayPropertyDeclaration(propertyName, returnExpression); - TypeDeclarationSyntax newTypeDeclaration = SyntaxRefactorings.AddAttributeLists(typeDeclaration, keepDocumentationCommentOnTop: true, attributeList); + newTypeDeclaration = SyntaxRefactorings.AddAttributeLists(newTypeDeclaration, keepDocumentationCommentOnTop: true, attributeList); newTypeDeclaration = MemberDeclarationInserter.Default.Insert(newTypeDeclaration, propertyDeclaration);