From 0cda3ec90e1adc2a5aa333a60bd657af57e9ae2a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 22 Nov 2024 21:44:34 -0800 Subject: [PATCH 01/15] Fix formatting when making an accessor readonly --- ...MakeStructMemberReadOnlyCodeFixProvider.cs | 1 - .../MakeStructMemberReadOnlyTests.cs | 34 +++++++++++++ .../CodeGeneration/CSharpSyntaxGenerator.cs | 51 ++++++++++--------- .../SyntaxFacts/CSharpAccessibilityFacts.cs | 6 ++- 4 files changed, 66 insertions(+), 26 deletions(-) diff --git a/src/Analyzers/CSharp/CodeFixes/MakeStructMemberReadOnly/CSharpMakeStructMemberReadOnlyCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/MakeStructMemberReadOnly/CSharpMakeStructMemberReadOnlyCodeFixProvider.cs index e18ea95725837..5fbc782c52ab5 100644 --- a/src/Analyzers/CSharp/CodeFixes/MakeStructMemberReadOnly/CSharpMakeStructMemberReadOnlyCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/MakeStructMemberReadOnly/CSharpMakeStructMemberReadOnlyCodeFixProvider.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; diff --git a/src/Analyzers/CSharp/Tests/MakeStructMemberReadOnly/MakeStructMemberReadOnlyTests.cs b/src/Analyzers/CSharp/Tests/MakeStructMemberReadOnly/MakeStructMemberReadOnlyTests.cs index 9b914d0ea1da3..0ef176175dd9e 100644 --- a/src/Analyzers/CSharp/Tests/MakeStructMemberReadOnly/MakeStructMemberReadOnlyTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeStructMemberReadOnly/MakeStructMemberReadOnlyTests.cs @@ -2521,4 +2521,38 @@ internal struct Values ReferenceAssemblies = ReferenceAssemblies.Net.Net80, }.RunAsync(); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71500")] + public async Task TestMultipleAccessors() + { + await new VerifyCS.Test + { + TestCode = """ + struct S + { + public int M; + + public int Z + { + [|get|] => M; + set => M = value; + } + } + """, + FixedCode = """ + struct S + { + public int M; + + public int Z + { + readonly get => M; + set => M = value; + } + } + """, + LanguageVersion = LanguageVersion.CSharp12, + ReferenceAssemblies = ReferenceAssemblies.Net.Net80, + }.RunAsync(); + } } diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index 781feb87fa332..f93ce6228aeff 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -1669,79 +1669,82 @@ private static SyntaxTokenList AsModifierList(Accessibility accessibility, Decla switch (accessibility) { case Accessibility.Internal: - list.Add(InternalKeyword); + list.Add(WithSpace(InternalKeyword)); break; case Accessibility.Public: - list.Add(PublicKeyword); + list.Add(WithSpace(PublicKeyword)); break; case Accessibility.Private: - list.Add(PrivateKeyword); + list.Add(WithSpace(PrivateKeyword)); break; case Accessibility.Protected: - list.Add(ProtectedKeyword); + list.Add(WithSpace(ProtectedKeyword)); break; case Accessibility.ProtectedOrInternal: - list.Add(ProtectedKeyword); - list.Add(InternalKeyword); + list.Add(WithSpace(ProtectedKeyword)); + list.Add(WithSpace(InternalKeyword)); break; case Accessibility.ProtectedAndInternal: - list.Add(PrivateKeyword); - list.Add(ProtectedKeyword); + list.Add(WithSpace(PrivateKeyword)); + list.Add(WithSpace(ProtectedKeyword)); break; case Accessibility.NotApplicable: break; } if (modifiers.IsFile) - list.Add(FileKeyword); + list.Add(WithSpace(FileKeyword)); if (modifiers.IsAbstract) - list.Add(AbstractKeyword); + list.Add(WithSpace(AbstractKeyword)); if (modifiers.IsNew) - list.Add(NewKeyword); + list.Add(WithSpace(NewKeyword)); if (modifiers.IsSealed) - list.Add(SealedKeyword); + list.Add(WithSpace(SealedKeyword)); if (modifiers.IsOverride) - list.Add(OverrideKeyword); + list.Add(WithSpace(OverrideKeyword)); if (modifiers.IsVirtual) - list.Add(VirtualKeyword); + list.Add(WithSpace(VirtualKeyword)); if (modifiers.IsStatic) - list.Add(StaticKeyword); + list.Add(WithSpace(StaticKeyword)); if (modifiers.IsAsync) - list.Add(AsyncKeyword); + list.Add(WithSpace(AsyncKeyword)); if (modifiers.IsConst) - list.Add(ConstKeyword); + list.Add(WithSpace(ConstKeyword)); if (modifiers.IsReadOnly) - list.Add(ReadOnlyKeyword); + list.Add(WithSpace(ReadOnlyKeyword)); if (modifiers.IsUnsafe) - list.Add(UnsafeKeyword); + list.Add(WithSpace(UnsafeKeyword)); if (modifiers.IsVolatile) - list.Add(VolatileKeyword); + list.Add(WithSpace(VolatileKeyword)); if (modifiers.IsExtern) - list.Add(ExternKeyword); + list.Add(WithSpace(ExternKeyword)); if (modifiers.IsRequired) - list.Add(RequiredKeyword); + list.Add(WithSpace(RequiredKeyword)); // partial and ref must be last if (modifiers.IsRef) - list.Add(RefKeyword); + list.Add(WithSpace(RefKeyword)); if (modifiers.IsPartial) - list.Add(PartialKeyword); + list.Add(WithSpace(PartialKeyword)); return [.. list]; + + SyntaxToken WithSpace(SyntaxToken token) + => token.WithoutLeadingTrivia().WithTrailingTrivia(SyntaxFactory.ElasticSpace); } private protected override SyntaxNode TypeParameter(string name) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs index d86f5e3b53acf..d1a339d6b2233 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs @@ -100,7 +100,11 @@ public Accessibility GetAccessibility(SyntaxNode declaration) return accessibility; } - public static void GetAccessibilityAndModifiers(SyntaxTokenList modifierList, out Accessibility accessibility, out DeclarationModifiers modifiers, out bool isDefault) + public static void GetAccessibilityAndModifiers( + SyntaxTokenList modifierList, + out Accessibility accessibility, + out DeclarationModifiers modifiers, + out bool isDefault) { accessibility = Accessibility.NotApplicable; modifiers = DeclarationModifiers.None; From d0788f28e8c7d4ffbfe362de350562f31711e88d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 22 Nov 2024 22:12:14 -0800 Subject: [PATCH 02/15] Simplify --- .../CodeGeneration/CSharpSyntaxGenerator.cs | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index f93ce6228aeff..3ddcac5dc7fdf 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -1669,82 +1669,82 @@ private static SyntaxTokenList AsModifierList(Accessibility accessibility, Decla switch (accessibility) { case Accessibility.Internal: - list.Add(WithSpace(InternalKeyword)); + list.Add(InternalKeyword); break; case Accessibility.Public: - list.Add(WithSpace(PublicKeyword)); + list.Add(PublicKeyword); break; case Accessibility.Private: - list.Add(WithSpace(PrivateKeyword)); + list.Add(PrivateKeyword); break; case Accessibility.Protected: - list.Add(WithSpace(ProtectedKeyword)); + list.Add(ProtectedKeyword); break; case Accessibility.ProtectedOrInternal: - list.Add(WithSpace(ProtectedKeyword)); - list.Add(WithSpace(InternalKeyword)); + list.Add(ProtectedKeyword); + list.Add(InternalKeyword); break; case Accessibility.ProtectedAndInternal: - list.Add(WithSpace(PrivateKeyword)); - list.Add(WithSpace(ProtectedKeyword)); + list.Add(PrivateKeyword); + list.Add(ProtectedKeyword); break; case Accessibility.NotApplicable: break; } if (modifiers.IsFile) - list.Add(WithSpace(FileKeyword)); + list.Add(FileKeyword); if (modifiers.IsAbstract) - list.Add(WithSpace(AbstractKeyword)); + list.Add(AbstractKeyword); if (modifiers.IsNew) - list.Add(WithSpace(NewKeyword)); + list.Add(NewKeyword); if (modifiers.IsSealed) - list.Add(WithSpace(SealedKeyword)); + list.Add(SealedKeyword); if (modifiers.IsOverride) - list.Add(WithSpace(OverrideKeyword)); + list.Add(OverrideKeyword); if (modifiers.IsVirtual) - list.Add(WithSpace(VirtualKeyword)); + list.Add(VirtualKeyword); if (modifiers.IsStatic) - list.Add(WithSpace(StaticKeyword)); + list.Add(StaticKeyword); if (modifiers.IsAsync) - list.Add(WithSpace(AsyncKeyword)); + list.Add(AsyncKeyword); if (modifiers.IsConst) - list.Add(WithSpace(ConstKeyword)); + list.Add(ConstKeyword); if (modifiers.IsReadOnly) - list.Add(WithSpace(ReadOnlyKeyword)); + list.Add(ReadOnlyKeyword); if (modifiers.IsUnsafe) - list.Add(WithSpace(UnsafeKeyword)); + list.Add(UnsafeKeyword); if (modifiers.IsVolatile) - list.Add(WithSpace(VolatileKeyword)); + list.Add(VolatileKeyword); if (modifiers.IsExtern) - list.Add(WithSpace(ExternKeyword)); + list.Add(ExternKeyword); if (modifiers.IsRequired) - list.Add(WithSpace(RequiredKeyword)); + list.Add(RequiredKeyword); // partial and ref must be last if (modifiers.IsRef) - list.Add(WithSpace(RefKeyword)); + list.Add(RefKeyword); if (modifiers.IsPartial) - list.Add(WithSpace(PartialKeyword)); + list.Add(PartialKeyword); - return [.. list]; + for (int i = 0, n = list.Count; i < n; i++) + list[i] = list[i].WithoutLeadingTrivia().WithTrailingTrivia(SyntaxFactory.ElasticSpace); - SyntaxToken WithSpace(SyntaxToken token) - => token.WithoutLeadingTrivia().WithTrailingTrivia(SyntaxFactory.ElasticSpace); + return [.. list]; } private protected override SyntaxNode TypeParameter(string name) From b998252923c6a79036ffa15203459ef6d70f34e3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 22 Nov 2024 23:04:57 -0800 Subject: [PATCH 03/15] Update tests --- .../MakeLocalFunctionStaticTests.cs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs b/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs index 218b08660ad06..eaf7942a8ce35 100644 --- a/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs @@ -203,7 +203,7 @@ static async Task fibonacci(int n) } } """, -parseOptions: CSharp8ParseOptions); + parseOptions: CSharp8ParseOptions); } [Theory, Trait(Traits.Feature, Traits.Features.CodeActionsMakeLocalFunctionStatic)] @@ -226,15 +226,14 @@ void M() }} }} }}", -""" +$$""" using System; class C { void M() { - int x; - + int x;{{leadingTrivia}} static int fibonacci(int n) { return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); @@ -264,13 +263,13 @@ void M() }} }} }}", -""" +$$""" using System; class C { void M() - { + {{{leadingTrivia}} static int fibonacci(int n) { return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); @@ -304,7 +303,7 @@ bool otherFunction() }} }} }}", -""" +$$""" using System; class C @@ -314,8 +313,7 @@ void M() bool otherFunction() { return true; - } - + }{{leadingTrivia}} static int fibonacci(int n) { return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); @@ -343,15 +341,14 @@ void M() int [||]fibonacci(int n) => n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); }} }}", -""" +$$""" using System; class C { void M() { - bool otherFunction() => true; - + bool otherFunction() => true;{{leadingTrivia}} static int fibonacci(int n) => n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); } } From 0c74e7eb7d9f609cbaa964fd92943317e843e68b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 22 Nov 2024 23:05:39 -0800 Subject: [PATCH 04/15] Update tests --- .../MakeLocalFunctionStaticTests.cs | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs b/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs index eaf7942a8ce35..5482852c66fc9 100644 --- a/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs @@ -251,33 +251,35 @@ static int fibonacci(int n) public async Task TestLeadingTriviaAfterOpenBrace(string leadingTrivia) { await TestInRegularAndScriptAsync( -$@"using System; + $$""" + using System; -class C -{{ - void M() - {{{leadingTrivia} - int [||]fibonacci(int n) - {{ - return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); - }} - }} -}}", -$$""" -using System; + class C + { + void M() + {{{leadingTrivia}} + int [||]fibonacci(int n) + { + return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); + } + } + } + """, + $$""" + using System; -class C -{ - void M() - {{{leadingTrivia}} - static int fibonacci(int n) - { - return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); - } - } -} -""", -parseOptions: CSharp8ParseOptions); + class C + { + void M() + {{{leadingTrivia}} + static int fibonacci(int n) + { + return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); + } + } + } + """, + parseOptions: CSharp8ParseOptions); } [Theory, Trait(Traits.Feature, Traits.Features.CodeActionsMakeLocalFunctionStatic)] From 1f5da22ca58dbd5058fbe3e7fe52f908891f16a3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 08:57:37 -0800 Subject: [PATCH 05/15] Update tests --- .../AddAccessibilityModifiersFixAllTests.cs | 1 - .../AddAccessibilityModifiersTests.cs | 1 - .../MakeLocalFunctionStaticTests.cs | 56 ++++++++++--------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersFixAllTests.cs b/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersFixAllTests.cs index 866c7eef2df9a..8de7bf2451e7d 100644 --- a/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersFixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersFixAllTests.cs @@ -40,7 +40,6 @@ class {|FixAllInContainingType:Program|} var expected = """ Console.WriteLine("Hello, World!"); - internal class Program { } diff --git a/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs b/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs index 8f432ae3a5330..cc1d61ad081ce 100644 --- a/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs +++ b/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs @@ -114,7 +114,6 @@ public event Action e5 { add { } remove { } } event Action I.e6 { add { } remove { } } static C() { } - private C() { } public C(int i) { } diff --git a/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs b/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs index 5482852c66fc9..1f6a0b1f0cfde 100644 --- a/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeLocalFunctionStatic/MakeLocalFunctionStaticTests.cs @@ -213,35 +213,37 @@ static async Task fibonacci(int n) public async Task TestLeadingTriviaAfterSemicolon(string leadingTrivia) { await TestInRegularAndScriptAsync( -$@"using System; + $$""" + using System; -class C -{{ - void M() - {{ - int x;{leadingTrivia} - int [||]fibonacci(int n) - {{ - return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); - }} - }} -}}", -$$""" -using System; + class C + { + void M() + { + int x;{{leadingTrivia}} + int [||]fibonacci(int n) + { + return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); + } + } + } + """, + $$""" + using System; -class C -{ - void M() - { - int x;{{leadingTrivia}} - static int fibonacci(int n) - { - return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); - } - } -} -""", -parseOptions: CSharp8ParseOptions); + class C + { + void M() + { + int x;{{leadingTrivia}} + static int fibonacci(int n) + { + return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); + } + } + } + """, + parseOptions: CSharp8ParseOptions); } [Theory, Trait(Traits.Feature, Traits.Features.CodeActionsMakeLocalFunctionStatic)] From a70562342fda8562ac809c39c78ebdf332999e1b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:01:38 -0800 Subject: [PATCH 06/15] Fix --- .../ConvertProgramTransform_ProgramMain.cs | 10 +++++----- .../ConvertToProgramMainCodeFixProvider.cs | 10 +++------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs b/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs index bd8b54b33a3dc..559812ad39d31 100644 --- a/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs +++ b/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs @@ -76,7 +76,7 @@ private static async Task GenerateProgramClassAsync( var programType = mainMethod.ContainingType; // Respect user settings on if they want explicit or implicit accessibility modifiers. - var useDeclaredAccessibity = accessibilityModifiersRequired is AccessibilityModifiersRequired.ForNonInterfaceMembers or AccessibilityModifiersRequired.Always; + var useDeclaredAccessibility = accessibilityModifiersRequired is AccessibilityModifiersRequired.ForNonInterfaceMembers or AccessibilityModifiersRequired.Always; var root = (CompilationUnitSyntax)await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var generator = document.GetRequiredLanguageService(); @@ -86,10 +86,10 @@ private static async Task GenerateProgramClassAsync( var method = (MethodDeclarationSyntax)generator.MethodDeclaration( mainMethod, WellKnownMemberNames.EntryPointMethodName, - GenerateProgramMainStatements(root, out var leadingTrivia)); + GenerateProgramMainStatements(root, out var leadingTrivia)).WithPrependedLeadingTrivia(ElasticMarker); method = method.WithReturnType(method.ReturnType.WithAdditionalAnnotations(Simplifier.AddImportsAnnotation)); method = (MethodDeclarationSyntax)generator.WithAccessibility( - method, useDeclaredAccessibity ? mainMethod.DeclaredAccessibility : Accessibility.NotApplicable); + method, useDeclaredAccessibility ? mainMethod.DeclaredAccessibility : Accessibility.NotApplicable); // Workaround for simplification not being ready when we generate a new file. Substitute System.String[] // with string[]. @@ -101,9 +101,9 @@ private static async Task GenerateProgramClassAsync( // If we dodn't have any suitable class declaration in the same file then generate it return FixupComments((ClassDeclarationSyntax)generator.ClassDeclaration( WellKnownMemberNames.TopLevelStatementsEntryPointTypeName, - accessibility: useDeclaredAccessibity ? programType.DeclaredAccessibility : Accessibility.NotApplicable, + accessibility: useDeclaredAccessibility ? programType.DeclaredAccessibility : Accessibility.NotApplicable, modifiers: hasExistingPart ? DeclarationModifiers.Partial : DeclarationModifiers.None, - members: new[] { method }).WithLeadingTrivia(leadingTrivia)); + members: [method]).WithLeadingTrivia(leadingTrivia)); } else { diff --git a/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeFixProvider.cs b/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeFixProvider.cs index 66fb3d762e5c3..76307c38ca7ea 100644 --- a/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeFixProvider.cs @@ -21,14 +21,10 @@ namespace Microsoft.CodeAnalysis.CSharp.ConvertProgram; using static ConvertProgramTransform; [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.ConvertToProgramMain), Shared] -internal class ConvertToProgramMainCodeFixProvider : SyntaxEditorBasedCodeFixProvider +[method: ImportingConstructor] +[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] +internal sealed class ConvertToProgramMainCodeFixProvider() : SyntaxEditorBasedCodeFixProvider { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public ConvertToProgramMainCodeFixProvider() - { - } - public override ImmutableArray FixableDiagnosticIds => [IDEDiagnosticIds.UseProgramMainId]; From 5e0bb0b1a7c35b37acccc34cbb3050d64b72dabc Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:03:10 -0800 Subject: [PATCH 07/15] Raw strings --- .../ConvertToProgramMainAnalyzerTests.cs | 714 +++++++++--------- 1 file changed, 370 insertions(+), 344 deletions(-) diff --git a/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs b/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs index 929676950bda8..8e3ad0c615344 100644 --- a/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs +++ b/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs @@ -21,9 +21,9 @@ public class ConvertToProgramMainAnalyzerTests [Fact] public async Task NotOfferedWhenUserPrefersTopLevelStatements() { - var code = @" -System.Console.WriteLine(0); -"; + var code = """ + System.Console.WriteLine(0); + """; await new VerifyCS.Test { @@ -37,15 +37,15 @@ public async Task NotOfferedWhenUserPrefersTopLevelStatements() [Fact] public async Task NotOfferedWhenUserPrefersProgramMainButNoTopLevelStatements() { - var code = @" -class C -{ - void M() - { - System.Console.WriteLine(0); - } -} -"; + var code = """ + class C + { + void M() + { + System.Console.WriteLine(0); + } + } + """; await new VerifyCS.Test { @@ -60,17 +60,20 @@ public async Task OfferedWhenUserPrefersProgramMainAndTopLevelStatements_Silent( { await new VerifyCS.Test { - TestCode = @"{|IDE0211: -System.Console.WriteLine(0); -|}", - FixedCode = @" -internal class Program -{ - private static void Main(string[] args) - { - System.Console.WriteLine(0); - } -}", + TestCode = """ + {|IDE0211: + System.Console.WriteLine(0); + |} + """, + FixedCode = """ + internal class Program + { + private static void Main(string[] args) + { + System.Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Silent } }, @@ -82,19 +85,23 @@ public async Task TestHeader1() { await new VerifyCS.Test { - TestCode = @"{|IDE0211:// This is a file banner + TestCode = """ + {|IDE0211:// This is a file banner -System.Console.WriteLine(0); -|}", - FixedCode = @"// This is a file banner + System.Console.WriteLine(0); + |} + """, + FixedCode = """ + // This is a file banner -internal class Program -{ - private static void Main(string[] args) - { - System.Console.WriteLine(0); - } -}", + internal class Program + { + private static void Main(string[] args) + { + System.Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Silent } }, @@ -106,21 +113,25 @@ public async Task TestHeader2() { await new VerifyCS.Test { - TestCode = @"{|IDE0211:// This is a file banner -using System; - -System.Console.WriteLine(0); -|}", - FixedCode = @"// This is a file banner -using System; - -internal class Program -{ - private static void Main(string[] args) - { - Console.WriteLine(0); - } -}", + TestCode = """ + {|IDE0211:// This is a file banner + using System; + + System.Console.WriteLine(0); + |} + """, + FixedCode = """ + // This is a file banner + using System; + + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Silent } }, @@ -130,9 +141,9 @@ private static void Main(string[] args) [Fact] public async Task NotOfferedInLibrary() { - var code = @" -{|CS8805:System.Console.WriteLine(0);|} -"; + var code = """ + {|CS8805:System.Console.WriteLine(0);|} + """; await new VerifyCS.Test { @@ -145,9 +156,9 @@ public async Task NotOfferedInLibrary() [Fact] public async Task NotOfferedWhenSuppressed() { - var code = @" -System.Console.WriteLine(0); -"; + var code = """ + System.Console.WriteLine(0); + """; await new VerifyCS.Test { @@ -163,17 +174,18 @@ public async Task OfferedWhenUserPrefersProgramMainAndTopLevelStatements_Suggest { await new VerifyCS.Test { - TestCode = @" -{|IDE0211:System|}.Console.WriteLine(0); -", - FixedCode = @" -internal class Program -{ - private static void Main(string[] args) - { - System.Console.WriteLine(0); - } -}", + TestCode = """ + {|IDE0211:System|}.Console.WriteLine(0); + """, + FixedCode = """ + internal class Program + { + private static void Main(string[] args) + { + System.Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -185,17 +197,18 @@ public async Task PreferNoAccessibility() { await new VerifyCS.Test { - TestCode = @" -{|IDE0211:System|}.Console.WriteLine(0); -", - FixedCode = @" -class Program -{ - static void Main(string[] args) - { - System.Console.WriteLine(0); - } -}", + TestCode = """ + {|IDE0211:System|}.Console.WriteLine(0); + """, + FixedCode = """ + class Program + { + static void Main(string[] args) + { + System.Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = @@ -211,21 +224,22 @@ public async Task TestWithExistingUsings() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -{|IDE0211:Console|}.WriteLine(0); -", - FixedCode = @" -using System; + {|IDE0211:Console|}.WriteLine(0); + """, + FixedCode = """ + using System; -internal class Program -{ - private static void Main(string[] args) - { - Console.WriteLine(0); - } -}", + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -237,25 +251,26 @@ public async Task TestWithNumericReturn() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -{|IDE0211:Console|}.WriteLine(0); + {|IDE0211:Console|}.WriteLine(0); -return 0; -", - FixedCode = @" -using System; - -internal class Program -{ - private static int Main(string[] args) - { - Console.WriteLine(0); + return 0; + """, + FixedCode = """ + using System; - return 0; - } -}", + internal class Program + { + private static int Main(string[] args) + { + Console.WriteLine(0); + + return 0; + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -267,33 +282,34 @@ public async Task TestWithLocalFunction() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -{|IDE0211:Console|}.WriteLine(0); + {|IDE0211:Console|}.WriteLine(0); -void M() -{ -} - -return 0; -", - FixedCode = @" -using System; - -internal class Program -{ - private static int Main(string[] args) - { - Console.WriteLine(0); + void M() + { + } - void M() - { - } + return 0; + """, + FixedCode = """ + using System; - return 0; - } -}", + internal class Program + { + private static int Main(string[] args) + { + Console.WriteLine(0); + + void M() + { + } + + return 0; + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -305,22 +321,23 @@ public async Task TestWithAwait() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -{|IDE0211:await|} Console.Out.WriteLineAsync(); -", - FixedCode = @" -using System; -using System.Threading.Tasks; + {|IDE0211:await|} Console.Out.WriteLineAsync(); + """, + FixedCode = """ + using System; + using System.Threading.Tasks; -internal class Program -{ - private static async Task Main(string[] args) - { - await Console.Out.WriteLineAsync(); - } -}", + internal class Program + { + private static async Task Main(string[] args) + { + await Console.Out.WriteLineAsync(); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -332,26 +349,27 @@ public async Task TestWithAwaitAndNumericReturn() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -{|IDE0211:await|} Console.Out.WriteLineAsync(); + {|IDE0211:await|} Console.Out.WriteLineAsync(); -return 0; -", - FixedCode = @" -using System; -using System.Threading.Tasks; - -internal class Program -{ - private static async Task Main(string[] args) - { - await Console.Out.WriteLineAsync(); + return 0; + """, + FixedCode = """ + using System; + using System.Threading.Tasks; - return 0; - } -}", + internal class Program + { + private static async Task Main(string[] args) + { + await Console.Out.WriteLineAsync(); + + return 0; + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -363,23 +381,24 @@ public async Task TestNormalCommentStaysInsideMainIfTouchingStatement() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -// This comment probably describes logic of the statement below -{|IDE0211:Console|}.WriteLine(0); -", - FixedCode = @" -using System; + // This comment probably describes logic of the statement below + {|IDE0211:Console|}.WriteLine(0); + """, + FixedCode = """ + using System; -internal class Program -{ - private static void Main(string[] args) - { - // This comment probably describes logic of the statement below - Console.WriteLine(0); - } -}", + internal class Program + { + private static void Main(string[] args) + { + // This comment probably describes logic of the statement below + Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -391,25 +410,26 @@ public async Task TestNormalCommentMovesIfNotTouching() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -// This comment probably does not describe the logic of the statement below + // This comment probably does not describe the logic of the statement below -{|IDE0211:Console|}.WriteLine(0); -", - FixedCode = @" -using System; + {|IDE0211:Console|}.WriteLine(0); + """, + FixedCode = """ + using System; -// This comment probably does not describe the logic of the statement below + // This comment probably does not describe the logic of the statement below -internal class Program -{ - private static void Main(string[] args) - { - Console.WriteLine(0); - } -}", + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -421,22 +441,23 @@ public async Task TestTopLevelStatementExplanationCommentRemoved() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -// See https://aka.ms/new-console-template for more information -{|IDE0211:Console|}.WriteLine(0); -", - FixedCode = @" -using System; + // See https://aka.ms/new-console-template for more information + {|IDE0211:Console|}.WriteLine(0); + """, + FixedCode = """ + using System; -internal class Program -{ - private static void Main(string[] args) - { - Console.WriteLine(0); - } -}", + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -448,23 +469,24 @@ public async Task TestTopLevelStatementExplanationCommentRemoved2() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -// See https://aka.ms/new-console-template for more information + // See https://aka.ms/new-console-template for more information -{|IDE0211:Console|}.WriteLine(0); -", - FixedCode = @" -using System; + {|IDE0211:Console|}.WriteLine(0); + """, + FixedCode = """ + using System; -internal class Program -{ - private static void Main(string[] args) - { - Console.WriteLine(0); - } -}", + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -476,19 +498,20 @@ public async Task TestTopLevelStatementExplanationCommentRemoved3() { await new VerifyCS.Test { - TestCode = @" -// See https://aka.ms/new-console-template for more information + TestCode = """ + // See https://aka.ms/new-console-template for more information -{|IDE0211:System|}.Console.WriteLine(0); -", - FixedCode = @" -internal class Program -{ - private static void Main(string[] args) - { - System.Console.WriteLine(0); - } -}", + {|IDE0211:System|}.Console.WriteLine(0); + """, + FixedCode = """ + internal class Program + { + private static void Main(string[] args) + { + System.Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -500,18 +523,19 @@ public async Task TestTopLevelStatementExplanationCommentRemoved4() { await new VerifyCS.Test { - TestCode = @" -// See https://aka.ms/new-console-template for more information -{|IDE0211:System|}.Console.WriteLine(0); -", - FixedCode = @" -internal class Program -{ - private static void Main(string[] args) - { - System.Console.WriteLine(0); - } -}", + TestCode = """ + // See https://aka.ms/new-console-template for more information + {|IDE0211:System|}.Console.WriteLine(0); + """, + FixedCode = """ + internal class Program + { + private static void Main(string[] args) + { + System.Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -523,30 +547,30 @@ public async Task TestPreprocessorDirective1() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -#if true + #if true -{|IDE0211:Console|}.WriteLine(0); + {|IDE0211:Console|}.WriteLine(0); -#endif -", - FixedCode = @" -using System; + #endif + """, + FixedCode = """ + using System; -#if true + #if true -internal class Program -{ - private static void Main(string[] args) - { - Console.WriteLine(0); - } -} - -#endif -", + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } + + #endif + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -558,34 +582,34 @@ public async Task TestPreprocessorDirective2() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -#if true + #if true -{|IDE0211:Console|}.WriteLine(0); + {|IDE0211:Console|}.WriteLine(0); -return; + return; -#endif -", - FixedCode = @" -using System; + #endif + """, + FixedCode = """ + using System; -#if true + #if true -internal class Program -{ - private static void Main(string[] args) - { - Console.WriteLine(0); + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine(0); - return; - } -} + return; + } + } -#endif -", + #endif + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -597,28 +621,29 @@ public async Task TestHasExistingPart() { await new VerifyCS.Test { - TestCode = @" -using System; - -{|IDE0211:Console|}.WriteLine(0); + TestCode = """ + using System; -partial class Program -{ - int x; -} -", - FixedCode = @" -using System; + {|IDE0211:Console|}.WriteLine(0); -partial class Program -{ - int x; + partial class Program + { + int x; + } + """, + FixedCode = """ + using System; - private static void Main(string[] args) - { - Console.WriteLine(0); - } -}", + partial class Program + { + int x; + + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -635,28 +660,29 @@ public async Task TestHasExistingPart_KeepsModifiers(string modifier) { await new VerifyCS.Test { - TestCode = $@" -using System; - -{{|IDE0211:Console|}}.WriteLine(0); - -{modifier} partial class Program -{{ - static int x; -}} -", - FixedCode = $@" -using System; - -{modifier} partial class Program -{{ - static int x; - - private static void Main(string[] args) - {{ - Console.WriteLine(0); - }} -}}", + TestCode = $$""" + using System; + + {|IDE0211:Console|}.WriteLine(0); + + {{modifier}} partial class Program + { + static int x; + } + """, + FixedCode = $$""" + using System; + + {{modifier}} partial class Program + { + static int x; + + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } + """, LanguageVersion = LanguageVersion.CSharp11, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, @@ -668,32 +694,32 @@ public async Task TestBeforeExistingClass() { await new VerifyCS.Test { - TestCode = @" -using System; + TestCode = """ + using System; -{|IDE0211:Console|}.WriteLine(0); + {|IDE0211:Console|}.WriteLine(0); -class X -{ - int x; -} -", - FixedCode = @" -using System; + class X + { + int x; + } + """, + FixedCode = """ + using System; -internal class Program -{ - private static void Main(string[] args) - { - Console.WriteLine(0); - } -} + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine(0); + } + } -class X -{ - int x; -} -", + class X + { + int x; + } + """, LanguageVersion = LanguageVersion.CSharp9, TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion } }, From 59a968d52859384e97c19302511e233e06322ad2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:04:27 -0800 Subject: [PATCH 08/15] Fix --- src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs index fc5e10a37f257..d8358de04ebb1 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs @@ -122,7 +122,6 @@ static Task Main(string[] args) global using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; - internal class Program { private static Task Main(string[] args) From ffcb034e13a91de02c6b3811b2aa72dd94f52a92 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:05:35 -0800 Subject: [PATCH 09/15] Fix --- .../CSharp/Tests/MakeMemberStatic/MakeMemberStaticTests.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/MakeMemberStatic/MakeMemberStaticTests.cs b/src/Analyzers/CSharp/Tests/MakeMemberStatic/MakeMemberStaticTests.cs index f97a4f16e94ed..b143b4f55d74b 100644 --- a/src/Analyzers/CSharp/Tests/MakeMemberStatic/MakeMemberStaticTests.cs +++ b/src/Analyzers/CSharp/Tests/MakeMemberStatic/MakeMemberStaticTests.cs @@ -133,11 +133,8 @@ namespace NS public static class Foo { static int i; - static void M() { } - static object P { get; set; } - static event System.Action E; } } From 9fa8fc2f8a27099bb39039ff08c8f589be7402e6 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:11:56 -0800 Subject: [PATCH 10/15] Fix --- ...arpAddDebuggerDisplayCodeRefactoringProvider.cs | 14 ++++---------- .../ConvertProgramTransform_ProgramMain.cs | 2 +- ...actAddDebuggerDisplayCodeRefactoringProvider.cs | 2 +- .../CodeGeneration/CSharpSyntaxGenerator.cs | 5 ++++- .../Core/Portable/Editing/SyntaxGenerator.cs | 2 +- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Features/CSharp/Portable/AddDebuggerDisplay/CSharpAddDebuggerDisplayCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/AddDebuggerDisplay/CSharpAddDebuggerDisplayCodeRefactoringProvider.cs index d40331add1911..df736052d6640 100644 --- a/src/Features/CSharp/Portable/AddDebuggerDisplay/CSharpAddDebuggerDisplayCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/AddDebuggerDisplay/CSharpAddDebuggerDisplayCodeRefactoringProvider.cs @@ -14,17 +14,11 @@ namespace Microsoft.CodeAnalysis.CSharp.AddDebuggerDisplay; [ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = PredefinedCodeRefactoringProviderNames.AddDebuggerDisplay), Shared] -internal sealed class CSharpAddDebuggerDisplayCodeRefactoringProvider - : AbstractAddDebuggerDisplayCodeRefactoringProvider< - TypeDeclarationSyntax, - MethodDeclarationSyntax> +[method: ImportingConstructor] +[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] +internal sealed class CSharpAddDebuggerDisplayCodeRefactoringProvider() + : AbstractAddDebuggerDisplayCodeRefactoringProvider { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpAddDebuggerDisplayCodeRefactoringProvider() - { - } - protected override bool CanNameofAccessNonPublicMembersFromAttributeArgument => true; protected override bool SupportsConstantInterpolatedStrings(Document document) diff --git a/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs b/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs index 559812ad39d31..c77aa79de36a2 100644 --- a/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs +++ b/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs @@ -86,7 +86,7 @@ private static async Task GenerateProgramClassAsync( var method = (MethodDeclarationSyntax)generator.MethodDeclaration( mainMethod, WellKnownMemberNames.EntryPointMethodName, - GenerateProgramMainStatements(root, out var leadingTrivia)).WithPrependedLeadingTrivia(ElasticMarker); + GenerateProgramMainStatements(root, out var leadingTrivia)); method = method.WithReturnType(method.ReturnType.WithAdditionalAnnotations(Simplifier.AddImportsAnnotation)); method = (MethodDeclarationSyntax)generator.WithAccessibility( method, useDeclaredAccessibility ? mainMethod.DeclaredAccessibility : Accessibility.NotApplicable); diff --git a/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs b/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs index ba770d65ba71c..e4e3ac8e3a9eb 100644 --- a/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs @@ -58,7 +58,7 @@ await GetRelevantTypeFromHeaderAsync(context).ConfigureAwait(false) ?? context.RegisterRefactoring(CodeAction.Create( FeaturesResources.Add_DebuggerDisplay_attribute, - c => ApplyAsync(document, type, debuggerAttributeTypeSymbol, c), + cancellationToken => ApplyAsync(document, type, debuggerAttributeTypeSymbol, cancellationToken), nameof(FeaturesResources.Add_DebuggerDisplay_attribute), priority)); } diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index 3ddcac5dc7fdf..97dd4081d5bbb 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -241,7 +241,7 @@ private protected override SyntaxNode MethodDeclaration( name = StripExplicitInterfaceName(name); - return SyntaxFactory.MethodDeclaration( + var method = SyntaxFactory.MethodDeclaration( attributeLists: default, modifiers: AsModifierList(accessibility, modifiers, SyntaxKind.MethodDeclaration), returnType: returnType != null ? (TypeSyntax)returnType : SyntaxFactory.PredefinedType(VoidKeyword), @@ -253,6 +253,9 @@ private protected override SyntaxNode MethodDeclaration( body: hasBody ? CreateBlock(statements) : null, expressionBody: null, semicolonToken: !hasBody ? SemicolonToken : default); + + // Ensure method will space itself properly within the members it is added to. + return method.WithPrependedLeadingTrivia(SyntaxFactory.ElasticMarker); } private static string StripExplicitInterfaceName(string name) diff --git a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs index e1dcfdf45f301..d6fd283100408 100644 --- a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs +++ b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs @@ -167,7 +167,7 @@ public SyntaxNode MethodDeclaration( IEnumerable? statements = null) { return MethodDeclaration( - name, parameters, typeParameters?.Select(n => TypeParameter(n)), returnType, accessibility, modifiers, statements); + name, parameters, typeParameters?.Select(TypeParameter), returnType, accessibility, modifiers, statements); } #pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters From 55a38db2ffd111833730fdbc5979019509d8992e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:15:14 -0800 Subject: [PATCH 11/15] Fix --- src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs | 2 -- .../ConvertProgram/ConvertToProgramMainAnalyzerTests.cs | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs index d8358de04ebb1..3a71fabe43350 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs @@ -53,7 +53,6 @@ static void Main(string[] args) var expected = """ using System; - internal class Program { private static void Main(string[] args) @@ -84,7 +83,6 @@ static void Main(string[] args) var expected = """ using System; using System.Collections.Generic; - internal class Program { private static void Main(string[] args) diff --git a/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs b/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs index 8e3ad0c615344..6ad14c16af2f7 100644 --- a/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs +++ b/src/Features/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs @@ -66,6 +66,7 @@ public async Task OfferedWhenUserPrefersProgramMainAndTopLevelStatements_Silent( |} """, FixedCode = """ + internal class Program { private static void Main(string[] args) From 1295d2555b4ffa69a22699e3cd0acba22ed200cb Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:18:30 -0800 Subject: [PATCH 12/15] Change --- .../CodeGeneration/CSharpSyntaxGenerator.cs | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index 97dd4081d5bbb..489f36e5c6068 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -241,9 +241,11 @@ private protected override SyntaxNode MethodDeclaration( name = StripExplicitInterfaceName(name); - var method = SyntaxFactory.MethodDeclaration( + return SyntaxFactory.MethodDeclaration( attributeLists: default, - modifiers: AsModifierList(accessibility, modifiers, SyntaxKind.MethodDeclaration), + // Pass `withLeadingElasticMarker: true` to ensure method will space itself properly within the members it + // is added to. + modifiers: AsModifierList(accessibility, modifiers, SyntaxKind.MethodDeclaration, withLeadingElasticMarker: true), returnType: returnType != null ? (TypeSyntax)returnType : SyntaxFactory.PredefinedType(VoidKeyword), explicitInterfaceSpecifier: null, identifier: name.ToIdentifierToken(), @@ -253,9 +255,6 @@ private protected override SyntaxNode MethodDeclaration( body: hasBody ? CreateBlock(statements) : null, expressionBody: null, semicolonToken: !hasBody ? SemicolonToken : default); - - // Ensure method will space itself properly within the members it is added to. - return method.WithPrependedLeadingTrivia(SyntaxFactory.ElasticMarker); } private static string StripExplicitInterfaceName(string name) @@ -1662,10 +1661,17 @@ private static SyntaxNode SetModifierTokens(SyntaxNode declaration, SyntaxTokenL _ => declaration, }; - private static SyntaxTokenList AsModifierList(Accessibility accessibility, DeclarationModifiers modifiers, SyntaxKind kind) - => AsModifierList(accessibility, GetAllowedModifiers(kind) & modifiers); + private static SyntaxTokenList AsModifierList( + Accessibility accessibility, + DeclarationModifiers modifiers, + SyntaxKind kind, + bool withLeadingElasticMarker = false) + => AsModifierList(accessibility, GetAllowedModifiers(kind) & modifiers, withLeadingElasticMarker); - private static SyntaxTokenList AsModifierList(Accessibility accessibility, DeclarationModifiers modifiers) + private static SyntaxTokenList AsModifierList( + Accessibility accessibility, + DeclarationModifiers modifiers, + bool withLeadingElasticMarker = false) { using var _ = ArrayBuilder.GetInstance(out var list); @@ -1745,7 +1751,12 @@ private static SyntaxTokenList AsModifierList(Accessibility accessibility, Decla list.Add(PartialKeyword); for (int i = 0, n = list.Count; i < n; i++) - list[i] = list[i].WithoutLeadingTrivia().WithTrailingTrivia(SyntaxFactory.ElasticSpace); + { + if (!withLeadingElasticMarker) + list[i] = list[i].WithoutLeadingTrivia(); + + list[i] = list[i].WithTrailingTrivia(SyntaxFactory.ElasticSpace); + } return [.. list]; } From 32573302292c67aa623016837a96ccc731ee0dbf Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:23:48 -0800 Subject: [PATCH 13/15] Docs --- .../CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index 489f36e5c6068..fa7827cd7f755 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -1752,6 +1752,9 @@ private static SyntaxTokenList AsModifierList( for (int i = 0, n = list.Count; i < n; i++) { + // By default, do not place leading elastic trivia on modifiers we make. Just because something is + // adding/removing/modifying modifiers does not mean we want the parent construct to change its formatting + // respective to what's around it. if (!withLeadingElasticMarker) list[i] = list[i].WithoutLeadingTrivia(); From 56fd00c95a8dd39b17f6d7c272126da993618787 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sat, 23 Nov 2024 09:26:08 -0800 Subject: [PATCH 14/15] Revert --- .../CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs index d1a339d6b2233..d86f5e3b53acf 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Services/SyntaxFacts/CSharpAccessibilityFacts.cs @@ -100,11 +100,7 @@ public Accessibility GetAccessibility(SyntaxNode declaration) return accessibility; } - public static void GetAccessibilityAndModifiers( - SyntaxTokenList modifierList, - out Accessibility accessibility, - out DeclarationModifiers modifiers, - out bool isDefault) + public static void GetAccessibilityAndModifiers(SyntaxTokenList modifierList, out Accessibility accessibility, out DeclarationModifiers modifiers, out bool isDefault) { accessibility = Accessibility.NotApplicable; modifiers = DeclarationModifiers.None; From 5278256e0307df9d6b515b67de6d56d366516a8f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 24 Nov 2024 17:28:14 -0800 Subject: [PATCH 15/15] Simplify --- .../CodeGeneration/CSharpSyntaxGenerator.cs | 68 ++++++------------- 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs index fa7827cd7f755..b9e11bafa9288 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs @@ -1701,54 +1701,24 @@ private static SyntaxTokenList AsModifierList( break; } - if (modifiers.IsFile) - list.Add(FileKeyword); - - if (modifiers.IsAbstract) - list.Add(AbstractKeyword); - - if (modifiers.IsNew) - list.Add(NewKeyword); - - if (modifiers.IsSealed) - list.Add(SealedKeyword); - - if (modifiers.IsOverride) - list.Add(OverrideKeyword); - - if (modifiers.IsVirtual) - list.Add(VirtualKeyword); - - if (modifiers.IsStatic) - list.Add(StaticKeyword); - - if (modifiers.IsAsync) - list.Add(AsyncKeyword); - - if (modifiers.IsConst) - list.Add(ConstKeyword); - - if (modifiers.IsReadOnly) - list.Add(ReadOnlyKeyword); - - if (modifiers.IsUnsafe) - list.Add(UnsafeKeyword); - - if (modifiers.IsVolatile) - list.Add(VolatileKeyword); - - if (modifiers.IsExtern) - list.Add(ExternKeyword); - - if (modifiers.IsRequired) - list.Add(RequiredKeyword); + AddIf(modifiers.IsFile, FileKeyword); + AddIf(modifiers.IsAbstract, AbstractKeyword); + AddIf(modifiers.IsNew, NewKeyword); + AddIf(modifiers.IsSealed, SealedKeyword); + AddIf(modifiers.IsOverride, OverrideKeyword); + AddIf(modifiers.IsVirtual, VirtualKeyword); + AddIf(modifiers.IsStatic, StaticKeyword); + AddIf(modifiers.IsAsync, AsyncKeyword); + AddIf(modifiers.IsConst, ConstKeyword); + AddIf(modifiers.IsReadOnly, ReadOnlyKeyword); + AddIf(modifiers.IsUnsafe, UnsafeKeyword); + AddIf(modifiers.IsVolatile, VolatileKeyword); + AddIf(modifiers.IsExtern, ExternKeyword); + AddIf(modifiers.IsRequired, RequiredKeyword); // partial and ref must be last - if (modifiers.IsRef) - list.Add(RefKeyword); - - if (modifiers.IsPartial) - list.Add(PartialKeyword); + AddIf(modifiers.IsRef, RefKeyword); + AddIf(modifiers.IsPartial, PartialKeyword); for (int i = 0, n = list.Count; i < n; i++) { @@ -1762,6 +1732,12 @@ private static SyntaxTokenList AsModifierList( } return [.. list]; + + void AddIf(bool test, SyntaxToken token) + { + if (test) + list.Add(token); + } } private protected override SyntaxNode TypeParameter(string name)