From 1c5303de6656d63a5788c6150b9b2f772ae886bd Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 16 Jul 2021 08:48:52 +0200 Subject: [PATCH 01/29] Add prefer trailing commas code-style option --- .../Portable/CodeGeneration/EnumMemberGenerator.cs | 13 +++++++------ .../CSharp/CodeStyle/CSharpCodeStyleOptions.cs | 6 ++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs index d5bc0b1225291..00de9c3f8cfed 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Shared.Utilities; @@ -26,15 +27,10 @@ internal static EnumDeclarationSyntax AddEnumMemberTo(EnumDeclarationSyntax dest var member = GenerateEnumMemberDeclaration(enumMember, destination, options); - if (members.Count == 0) + if (members.Count == 0 || members.LastOrDefault().IsKind(SyntaxKind.CommaToken)) { members.Add(member); } - else if (members.LastOrDefault().Kind() == SyntaxKind.CommaToken) - { - members.Add(member); - members.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); - } else { var lastMember = members.Last(); @@ -44,6 +40,11 @@ internal static EnumDeclarationSyntax AddEnumMemberTo(EnumDeclarationSyntax dest members.Add(member); } + if (options.Options.GetOption(CSharpCodeStyleOptions.PreferTrailingCommas).Value) + { + members.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); + } + return destination.EnsureOpenAndCloseBraceTokens() .WithMembers(SyntaxFactory.SeparatedList(members)); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs index 58b1de4eecbec..cedacd0096c0b 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs @@ -295,6 +295,12 @@ private static Option2> CreateUsingDirectiv EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental", CodeStyleOptions2.TrueWithSilentEnforcement), new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(AllowBlankLineAfterColonInConstructorInitializer)}")}); + public static readonly Option2> PreferTrailingCommas = CreateOption( + CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferTrailingCommas), + defaultValue: s_trueWithSuggestionEnforcement, + "csharp_style_prefer_trailing_commas", + $"TextEditor.CSharp.Specific.{nameof(PreferTrailingCommas)}"); + #if false public static readonly Option2> VarElsewhere = CreateOption( From 0d6b5bd78423c0eb9f7ed6a5663cc8b1c6a75f9d Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 16 Jul 2021 08:52:49 +0200 Subject: [PATCH 02/29] Simplify --- .../Portable/CodeGeneration/EnumMemberGenerator.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs index 00de9c3f8cfed..dc597d8a6e448 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs @@ -27,19 +27,16 @@ internal static EnumDeclarationSyntax AddEnumMemberTo(EnumDeclarationSyntax dest var member = GenerateEnumMemberDeclaration(enumMember, destination, options); - if (members.Count == 0 || members.LastOrDefault().IsKind(SyntaxKind.CommaToken)) - { - members.Add(member); - } - else + if (members.Count > 0 && !members.LastOrDefault().IsKind(SyntaxKind.CommaToken)) { var lastMember = members.Last(); var trailingTrivia = lastMember.GetTrailingTrivia(); members[members.Count - 1] = lastMember.WithTrailingTrivia(); members.Add(SyntaxFactory.Token(SyntaxKind.CommaToken).WithTrailingTrivia(trailingTrivia)); - members.Add(member); } + members.Add(member); + if (options.Options.GetOption(CSharpCodeStyleOptions.PreferTrailingCommas).Value) { members.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); From 26209134a5442a09c38d70c68618b1a2e9ea467c Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Tue, 18 Jan 2022 21:07:22 +0200 Subject: [PATCH 03/29] VS and editorconfig --- .../CSharpCodeStyleSettingsProvider.cs | 1 + .../AutomationObject.Style.cs | 6 +++++ .../Impl/Options/Formatting/StyleViewModel.cs | 22 +++++++++++++++++++ .../Core/Def/ServicesVSResources.resx | 3 +++ 4 files changed, 32 insertions(+) diff --git a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs index 7b370876367e7..d7c53dcabb955 100644 --- a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs +++ b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs @@ -151,6 +151,7 @@ private IEnumerable GetExpressionCodeStyleOptions(AnalyzerConf yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferRangeOperator, description: ServicesVSResources.Prefer_range_operator, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, description: CSharpVSResources.Prefer_implicit_object_creation_when_type_is_apparent, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTupleSwap, description: ServicesVSResources.Prefer_tuple_swap, editorConfigOptions, visualStudioOptions, updaterService, FileName); + yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTrailingCommas, description: ServicesVSResources.Prefer_trailing_commas, editorConfigOptions, visualStudioOptions, updaterService, FileName) } private IEnumerable GetPatternMatchingCodeStyleOptions(AnalyzerConfigOptions editorConfigOptions, OptionSet visualStudioOptions, OptionUpdater updaterService) diff --git a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs index 527c4b7de2e52..5736f747052e6 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs @@ -422,5 +422,11 @@ public string Style_NamespaceDeclarations get { return GetXmlOption(CSharpCodeStyleOptions.NamespaceDeclarations); } set { SetXmlOption(CSharpCodeStyleOptions.NamespaceDeclarations, value); } } + + public string Style_PreferTrailingCommas + { + get { return GetXmlOption(CSharpCodeStyleOptions.PreferTrailingCommas); } + set { SetXmlOption(CSharpCodeStyleOptions.PreferTrailingCommas, value); } + } } } diff --git a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs index 57acab1007e6c..1270567d0eabb 100644 --- a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs +++ b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs @@ -1118,6 +1118,26 @@ void M2(string[] args) //] }} }} +"; + + private static readonly string s_preferTrailingCommas = $@" +//[ + // {ServicesVSResources.Prefer_colon} + enum E + {{ + A, + B, + }} +//] +//[ + // {ServicesVSResources.Over_colon} + enum E + {{ + A, + B, + }} +//] +}} "; private static readonly string s_preferIsNullOverReferenceEquals = $@" @@ -2138,6 +2158,8 @@ internal StyleViewModel(OptionStore optionStore, IServiceProvider serviceProvide CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferTupleSwap, ServicesVSResources.Prefer_tuple_swap, s_preferTupleSwap, s_preferTupleSwap, this, optionStore, expressionPreferencesGroupTitle)); + CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferTrailingCommas, ServicesVSResources.Prefer_trailing_commas, s_preferTrailingCommas, s_preferTrailingCommas, this, optionStore, expressionPreferencesGroupTitle)); + AddExpressionBodyOptions(optionStore, expressionPreferencesGroupTitle); AddUnusedValueOptions(optionStore, expressionPreferencesGroupTitle); diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx index 5e006552b86b9..df40a6f183709 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.resx +++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx @@ -1903,4 +1903,7 @@ Additional information: {1} Prefer method group conversion + + Prefer trailing commas + \ No newline at end of file From 593f10fc1562f5f9cc60d2b3db607b97e3ff6064 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Tue, 18 Jan 2022 21:25:16 +0200 Subject: [PATCH 04/29] More fixes --- .../GenerateEnumMemberTests.cs | 100 +++++++++--------- .../CodeGeneration/EnumMemberGenerator.cs | 4 +- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateEnumMember/GenerateEnumMemberTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateEnumMember/GenerateEnumMemberTests.cs index 6214dc3078c50..d422e2940f97f 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateEnumMember/GenerateEnumMemberTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateEnumMember/GenerateEnumMemberTests.cs @@ -50,7 +50,7 @@ void Main() enum Color { - Red + Red, }"); } @@ -81,7 +81,7 @@ void Main() enum Color { Red, - Blue + Blue, }"); } @@ -145,7 +145,7 @@ enum Color { Red, Blue, - Green + Green, }"); } @@ -176,7 +176,7 @@ void Main() enum Color { Red = 0, - Blue = 1 + Blue = 1, }"); } @@ -207,7 +207,7 @@ void Main() enum Color { Red = 1, - Blue = 2 + Blue = 2, }"); } @@ -238,7 +238,7 @@ void Main() enum Color { Red = 2, - Blue = 4 + Blue = 4, }"); } @@ -273,7 +273,7 @@ enum Color Red = 1, Yellow = 2, Green = 4, - Blue = 8 + Blue = 8, }"); } @@ -306,7 +306,7 @@ enum Color { Red = 1, Green = 2, - Blue = 3 + Blue = 3, }"); } @@ -341,7 +341,7 @@ enum Color Yellow = 0, Red = 1, Green = 2, - Blue = 3 + Blue = 3, }"); } @@ -372,7 +372,7 @@ void Main() enum Color { Green = 5, - Blue = 6 + Blue = 6, }"); } @@ -403,7 +403,7 @@ void Main() enum Color { Green = 1 << 0, - Blue = 1 << 1 + Blue = 1 << 1, }"); } @@ -434,7 +434,7 @@ void Main() enum Color { Green = 1 << 5, - Blue = 1 << 6 + Blue = 1 << 6, }"); } @@ -467,7 +467,7 @@ enum Color { Red = 2, Green = 1 << 5, - Blue = 33 + Blue = 33, }"); } @@ -498,7 +498,7 @@ void Main() enum Color { Red = 0b01, - Blue = 0b10 + Blue = 0b10, }"); } @@ -529,7 +529,7 @@ void Main() enum Color { Red = 0x1, - Blue = 0x2 + Blue = 0x2, }"); } @@ -560,7 +560,7 @@ void Main() enum Color { Red = 0x9, - Blue = 0xA + Blue = 0xA, }"); } @@ -591,7 +591,7 @@ void Main() enum Color { Red = 0xF, - Blue = 0x10 + Blue = 0x10, }"); } @@ -622,7 +622,7 @@ void Main() enum Color { Red = int.MaxValue, - Blue = int.MinValue + Blue = int.MinValue, }"); } @@ -653,7 +653,7 @@ void Main() enum Color : ushort { Red = 65535, - Blue = 0 + Blue = 0, }"); } @@ -684,7 +684,7 @@ void Main() enum Color : long { Red = long.MaxValue, - Blue = long.MinValue + Blue = long.MinValue, }"); } @@ -715,7 +715,7 @@ void Main() enum Color : long { Red = 0b0111111111111111111111111111111111111111111111111111111111111111, - Blue = 0b1000000000000000000000000000000000000000000000000000000000000000 + Blue = 0b1000000000000000000000000000000000000000000000000000000000000000, }"); } @@ -746,7 +746,7 @@ void Main() enum Color : long { Red = 0x7FFFFFFFFFFFFFFF, - Blue = 0x8000000000000000 + Blue = 0x8000000000000000, }"); } @@ -778,7 +778,7 @@ void Main() enum Color : long { Red = 0xFFFFFFFFFFFFFFFF, - Blue + Blue, }"); } @@ -812,7 +812,7 @@ enum Color : long { Red = 0xFFFFFFFFFFFFFFFF, Green = 0x0, - Blue = 0x1 + Blue = 0x1, }"); } @@ -843,7 +843,7 @@ void Main() enum Color : long { Red = 0x414 / 2, - Blue = 523 + Blue = 523, }"); } @@ -874,7 +874,7 @@ void Main() enum Color : ulong { Red = ulong.MaxValue, - Blue = 0 + Blue = 0, }"); } @@ -905,7 +905,7 @@ void Main() enum Color : long { Red = -10, - Blue = -9 + Blue = -9, }"); } @@ -940,7 +940,7 @@ enum Color Red, Green, Yellow = -1, - Blue = 2 + Blue = 2, }"); } @@ -975,7 +975,7 @@ enum Color Red, Green = 10, Yellow, - Blue + Blue, }"); } @@ -1007,7 +1007,7 @@ static void Main(string[] args) enum Color { Red, - Blue + Blue, //Blue }"); } @@ -1040,7 +1040,7 @@ static void Main(string[] args) enum Color { Red, - Blue + Blue, /*Blue*/ }"); } @@ -1072,7 +1072,7 @@ void Main() enum Color { Red = int.MinValue, - Blue = -2147483647 + Blue = -2147483647, }"); } @@ -1103,7 +1103,7 @@ void Main() enum Color { Red = int.MinValue + 100, - Blue = -2147483547 + Blue = -2147483547, }"); } @@ -1134,7 +1134,7 @@ void Main() enum Color : byte { Red = 255, - Blue = 0 + Blue = 0, }"); } @@ -1167,7 +1167,7 @@ enum Color { Red = 1 << 1, Green = 1 << 2, - Blue = 1 << 3 + Blue = 1 << 3, }"); } @@ -1198,7 +1198,7 @@ void Main() enum Color { Red = 2 >> 1, - Blue = 2 + Blue = 2, }"); } @@ -1231,7 +1231,7 @@ enum Color { Red = int.MinValue, Green = 1, - Blue = 2 + Blue = 2, }"); } @@ -1264,7 +1264,7 @@ enum Circular { A = B, B, - C + C, }"); } @@ -1295,7 +1295,7 @@ void Main() enum Circular : byte { A = -2, - B + B, }"); } @@ -1334,7 +1334,7 @@ void Main() public new enum BaseColor { Yellow = 3, - Blue = 4 + Blue = 4, } } @@ -1383,7 +1383,7 @@ void Main() public enum BaseColor { Yellow = 3, - Blue = 4 + Blue = 4, } } @@ -1431,7 +1431,7 @@ public enum BaseColor { Red = 1, Green = 2, - Blue = 3 + Blue = 3, } }"); } @@ -1467,7 +1467,7 @@ enum Color Red, Green, Yellow = Green, - Blue = 2 + Blue = 2, }"); } @@ -1504,7 +1504,7 @@ enum Color Red, Green = 10, Yellow, - Blue + Blue, }"); } @@ -1533,7 +1533,7 @@ static void Main(string[] args) enum Weekday { Monday, - Tuesday + Tuesday, }"); } @@ -1565,7 +1565,7 @@ static void Main(string[] args) enum Color { Red, - @enum + @enum, }"); } @@ -1682,7 +1682,7 @@ void Main() { A = 1, B, - C + C, } class Program @@ -1721,7 +1721,7 @@ void Main() enum Color : long { Green = 1L << 0, - Blue = 1L << 1 + Blue = 1L << 1, }"); } @@ -1753,7 +1753,7 @@ void Main() enum Color : uint { Green = 1u << 0, - Blue = 1u << 1 + Blue = 1u << 1, }"); } @@ -1785,7 +1785,7 @@ void Main() enum Color : ulong { Green = 1UL << 0, - Blue = 1UL << 1 + Blue = 1UL << 1, }"); } } diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs index 1d0bc32f8855c..224a1b635e34b 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs @@ -26,7 +26,7 @@ internal static EnumDeclarationSyntax AddEnumMemberTo(EnumDeclarationSyntax dest var member = GenerateEnumMemberDeclaration(enumMember, destination, options, cancellationToken); - if (members.Count > 0 && !members.LastOrDefault().IsKind(SyntaxKind.CommaToken)) + if (members.Count > 0 && !members[^1].IsKind(SyntaxKind.CommaToken)) { var lastMember = members.Last(); var trailingTrivia = lastMember.GetTrailingTrivia(); @@ -36,7 +36,7 @@ internal static EnumDeclarationSyntax AddEnumMemberTo(EnumDeclarationSyntax dest members.Add(member); - if (options.Options.GetOption(CSharpCodeStyleOptions.PreferTrailingCommas).Value) + if (options.Preferences.Options.GetOption(CSharpCodeStyleOptions.PreferTrailingCommas).Value) { members.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); } From 94eb765ed4d9a8d0018cabcf44fde9f7a04b6616 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Tue, 18 Jan 2022 21:27:27 +0200 Subject: [PATCH 05/29] Update xlf --- .../CodeStyle/CSharpCodeStyleSettingsProvider.cs | 2 +- src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf | 5 +++++ .../Core/Def/xlf/ServicesVSResources.zh-Hans.xlf | 5 +++++ .../Core/Def/xlf/ServicesVSResources.zh-Hant.xlf | 5 +++++ 14 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs index d7c53dcabb955..7362d309c69b6 100644 --- a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs +++ b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs @@ -151,7 +151,7 @@ private IEnumerable GetExpressionCodeStyleOptions(AnalyzerConf yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferRangeOperator, description: ServicesVSResources.Prefer_range_operator, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, description: CSharpVSResources.Prefer_implicit_object_creation_when_type_is_apparent, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTupleSwap, description: ServicesVSResources.Prefer_tuple_swap, editorConfigOptions, visualStudioOptions, updaterService, FileName); - yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTrailingCommas, description: ServicesVSResources.Prefer_trailing_commas, editorConfigOptions, visualStudioOptions, updaterService, FileName) + yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTrailingCommas, description: ServicesVSResources.Prefer_trailing_commas, editorConfigOptions, visualStudioOptions, updaterService, FileName); } private IEnumerable GetPatternMatchingCodeStyleOptions(AnalyzerConfigOptions editorConfigOptions, OptionSet visualStudioOptions, OptionUpdater updaterService) diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index 91aa6b84acfbc..95acab050f204 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -1032,6 +1032,11 @@ Preferovat statické místní funkce + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Preferovat prohození řazené kolekce členů diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf index 9214803885316..852507f24e1d1 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf @@ -1032,6 +1032,11 @@ Statische lokale Funktionen bevorzugen + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Tupeltausch bevorzugen diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf index 95bdc345a9c42..bde018bb1119e 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf @@ -1032,6 +1032,11 @@ Preferir funciones locales estáticas + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Preferir el intercambio de tupla diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index c2f98dd332ac2..bab798699d91a 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -1032,6 +1032,11 @@ Préférer les fonctions locales statiques + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Préférer l'échange de tuples diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf index 7e0d381778a7a..bb9e69e2a8bac 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf @@ -1032,6 +1032,11 @@ Preferisci funzioni locali statiche + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Preferisci lo scambio di tuple diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf index b3100a936ca46..d8abcaf3ae8e2 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf @@ -1032,6 +1032,11 @@ 静的ローカル関数を優先する + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap タプル スワップを優先する diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf index 1db9539ee2c27..4fcea817e2c5b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf @@ -1032,6 +1032,11 @@ 정적 로컬 함수 선호 + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap 튜플 교환 선호 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index a143d4c773a03..0df9beb76af65 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -1032,6 +1032,11 @@ Preferuj statyczne funkcje lokalne + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Preferuj zamianę krotki diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index 4197537e2a0d9..19148a0d0cd6c 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -1032,6 +1032,11 @@ Preferir as funções locais estáticas + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Prefiro troca de tupla diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index 19f9a6da16b0a..c9f5d0e2c9440 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -1032,6 +1032,11 @@ Предпочитать статические локальные функции + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Предпочитать переключение кортежей diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index b85e07a628f81..5514407dcb4c0 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -1032,6 +1032,11 @@ Statik yerel işlevleri tercih et + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap Demet değiştirmeyi tercih et diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index c2ac3476cd0d5..e47034717ce51 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -1032,6 +1032,11 @@ 首选静态本地函数 + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap 首选元组交换 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf index 4ec614b139bc2..d92e9974c5866 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf @@ -1032,6 +1032,11 @@ 優先使用靜態區域函式 + + Prefer trailing commas + Prefer trailing commas + + Prefer tuple swap 偏好元組交換 From 6943fb098ed2479582e614cfd0355077fb6c0f24 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Tue, 18 Jan 2022 21:33:12 +0200 Subject: [PATCH 06/29] Update src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs --- .../CSharp/Impl/Options/Formatting/StyleViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs index 1270567d0eabb..40cc8350a813a 100644 --- a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs +++ b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs @@ -1134,7 +1134,7 @@ enum E enum E {{ A, - B, + B }} //] }} From 200863c2b1cab7f0e4d08bd0e5a995cc2527ffe8 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 5 Feb 2022 19:29:52 +0200 Subject: [PATCH 07/29] Singular comma --- .../CodeStyle/CSharpCodeStyleSettingsProvider.cs | 2 +- .../Options/AutomationObject/AutomationObject.Style.cs | 6 +++--- .../CSharp/Impl/Options/Formatting/StyleViewModel.cs | 4 ++-- src/VisualStudio/Core/Def/ServicesVSResources.resx | 4 ++-- .../Core/Def/xlf/ServicesVSResources.cs.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.de.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.es.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.fr.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.it.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.ja.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.ko.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.pl.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.pt-BR.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.ru.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.tr.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.zh-Hans.xlf | 6 +++--- .../Core/Def/xlf/ServicesVSResources.zh-Hant.xlf | 6 +++--- .../Portable/CodeGeneration/EnumMemberGenerator.cs | 2 +- .../CSharp/CodeStyle/CSharpCodeStyleOptions.cs | 10 +++++----- 19 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs index 7362d309c69b6..cf2947b2cf9fe 100644 --- a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs +++ b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs @@ -151,7 +151,7 @@ private IEnumerable GetExpressionCodeStyleOptions(AnalyzerConf yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferRangeOperator, description: ServicesVSResources.Prefer_range_operator, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, description: CSharpVSResources.Prefer_implicit_object_creation_when_type_is_apparent, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTupleSwap, description: ServicesVSResources.Prefer_tuple_swap, editorConfigOptions, visualStudioOptions, updaterService, FileName); - yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTrailingCommas, description: ServicesVSResources.Prefer_trailing_commas, editorConfigOptions, visualStudioOptions, updaterService, FileName); + yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTrailingComma, description: ServicesVSResources.Prefer_trailing_comma, editorConfigOptions, visualStudioOptions, updaterService, FileName); } private IEnumerable GetPatternMatchingCodeStyleOptions(AnalyzerConfigOptions editorConfigOptions, OptionSet visualStudioOptions, OptionUpdater updaterService) diff --git a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs index 5736f747052e6..6ec1f2110c63c 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs @@ -423,10 +423,10 @@ public string Style_NamespaceDeclarations set { SetXmlOption(CSharpCodeStyleOptions.NamespaceDeclarations, value); } } - public string Style_PreferTrailingCommas + public string Style_PreferTrailingComma { - get { return GetXmlOption(CSharpCodeStyleOptions.PreferTrailingCommas); } - set { SetXmlOption(CSharpCodeStyleOptions.PreferTrailingCommas, value); } + get { return GetXmlOption(CSharpCodeStyleOptions.PreferTrailingComma); } + set { SetXmlOption(CSharpCodeStyleOptions.PreferTrailingComma, value); } } } } diff --git a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs index 40cc8350a813a..5061b601c7174 100644 --- a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs +++ b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs @@ -1120,7 +1120,7 @@ void M2(string[] args) }} "; - private static readonly string s_preferTrailingCommas = $@" + private static readonly string s_preferTrailingComma = $@" //[ // {ServicesVSResources.Prefer_colon} enum E @@ -2158,7 +2158,7 @@ internal StyleViewModel(OptionStore optionStore, IServiceProvider serviceProvide CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferTupleSwap, ServicesVSResources.Prefer_tuple_swap, s_preferTupleSwap, s_preferTupleSwap, this, optionStore, expressionPreferencesGroupTitle)); - CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferTrailingCommas, ServicesVSResources.Prefer_trailing_commas, s_preferTrailingCommas, s_preferTrailingCommas, this, optionStore, expressionPreferencesGroupTitle)); + CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferTrailingComma, ServicesVSResources.Prefer_trailing_comma, s_preferTrailingComma, s_preferTrailingComma, this, optionStore, expressionPreferencesGroupTitle)); AddExpressionBodyOptions(optionStore, expressionPreferencesGroupTitle); AddUnusedValueOptions(optionStore, expressionPreferencesGroupTitle); diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx index df40a6f183709..8436784dc6965 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.resx +++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx @@ -1903,7 +1903,7 @@ Additional information: {1} Prefer method group conversion - - Prefer trailing commas + + Prefer trailing comma \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index 95acab050f204..66da26e7e2962 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -1032,9 +1032,9 @@ Preferovat statické místní funkce - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf index 852507f24e1d1..fc526f150d9ae 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf @@ -1032,9 +1032,9 @@ Statische lokale Funktionen bevorzugen - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf index bde018bb1119e..d377c0654b7a3 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf @@ -1032,9 +1032,9 @@ Preferir funciones locales estáticas - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index bab798699d91a..f1ea97283937b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -1032,9 +1032,9 @@ Préférer les fonctions locales statiques - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf index bb9e69e2a8bac..71a2f4e015760 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf @@ -1032,9 +1032,9 @@ Preferisci funzioni locali statiche - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf index d8abcaf3ae8e2..f0e69a27b1e77 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf @@ -1032,9 +1032,9 @@ 静的ローカル関数を優先する - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf index 4fcea817e2c5b..5be7bda382cc7 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf @@ -1032,9 +1032,9 @@ 정적 로컬 함수 선호 - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index 0df9beb76af65..cd8ed920b3cca 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -1032,9 +1032,9 @@ Preferuj statyczne funkcje lokalne - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index 19148a0d0cd6c..11b6a2dc302cf 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -1032,9 +1032,9 @@ Preferir as funções locais estáticas - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index c9f5d0e2c9440..01c7e499fb2b2 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -1032,9 +1032,9 @@ Предпочитать статические локальные функции - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index 5514407dcb4c0..fe7f91eb7b498 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -1032,9 +1032,9 @@ Statik yerel işlevleri tercih et - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index e47034717ce51..69a3df8770c3a 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -1032,9 +1032,9 @@ 首选静态本地函数 - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf index d92e9974c5866..8e94d355f0b8a 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf @@ -1032,9 +1032,9 @@ 優先使用靜態區域函式 - - Prefer trailing commas - Prefer trailing commas + + Prefer trailing comma + Prefer trailing comma diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs index 224a1b635e34b..54a363f49db2e 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs @@ -36,7 +36,7 @@ internal static EnumDeclarationSyntax AddEnumMemberTo(EnumDeclarationSyntax dest members.Add(member); - if (options.Preferences.Options.GetOption(CSharpCodeStyleOptions.PreferTrailingCommas).Value) + if (options.Preferences.Options.GetOption(CSharpCodeStyleOptions.PreferTrailingComma).Value) { members.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs index 737d0140b2e76..1c6cb707e8968 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs @@ -345,11 +345,11 @@ private static Option2> CreateN "csharp_style_prefer_method_group_conversion", "TextEditor.CSharp.Specific.PreferMethodGroupConversion"); - public static readonly Option2> PreferTrailingCommas = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferTrailingCommas), - defaultValue: s_trueWithSuggestionEnforcement, - "csharp_style_prefer_trailing_commas", - $"TextEditor.CSharp.Specific.{nameof(PreferTrailingCommas)}"); + public static readonly Option2> PreferTrailingComma = CreateOption( + CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferTrailingComma), + defaultValue: s_trueWithSilentEnforcement, + "csharp_style_prefer_trailing_comma", + $"TextEditor.CSharp.Specific.{nameof(PreferTrailingComma)}"); #if false From f5bda1347ce6235ceb53406e40475c4408063196 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 5 Feb 2022 19:46:54 +0200 Subject: [PATCH 08/29] Fix error --- .../CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs index 54a363f49db2e..2dd59f720a145 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs @@ -36,7 +36,7 @@ internal static EnumDeclarationSyntax AddEnumMemberTo(EnumDeclarationSyntax dest members.Add(member); - if (options.Preferences.Options.GetOption(CSharpCodeStyleOptions.PreferTrailingComma).Value) + if (options.Preferences.PreferTrailingComma) { members.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); } From 04a6ed00b05d6bec82e8c3f984827ab616d5002e Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 5 Feb 2022 19:59:53 +0200 Subject: [PATCH 09/29] Missing commit --- .../Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs index b82d4859e943d..5adef926cf4bf 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs @@ -55,6 +55,9 @@ public NamespaceDeclarationPreference NamespaceDeclarations public AddImportPlacement PreferredUsingDirectivePlacement => Options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement).Value; + public bool PreferTrailingComma + => Options.GetOption(CSharpCodeStyleOptions.PreferTrailingComma).Value; + public override bool PlaceImportsInsideNamespaces => PreferredUsingDirectivePlacement == AddImportPlacement.InsideNamespace; From 6a6313c554517e9079e1c6b77d98cab9f725839b Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 24 Jun 2022 09:44:21 +0200 Subject: [PATCH 10/29] Adapt implementation to recent refactoring --- .../CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs | 2 +- .../CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs index 40e10288198a1..2e2cb52e804e3 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/EnumMemberGenerator.cs @@ -36,7 +36,7 @@ internal static EnumDeclarationSyntax AddEnumMemberTo(EnumDeclarationSyntax dest members.Add(member); - if (options.Preferences.PreferTrailingComma) + if (info.Options.PreferTrailingComma.Value) { members.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs index fec7b194448a8..38006b09cef24 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs @@ -46,6 +46,7 @@ internal sealed class CSharpCodeGenerationOptions : CodeGenerationOptions, IEqua [DataMember] public CodeStyleOption2 PreferExpressionBodiedLambdas { get; init; } = s_whenPossibleWithSilentEnforcement; [DataMember] public CodeStyleOption2 PreferStaticLocalFunction { get; init; } = s_trueWithSuggestionEnforcement; [DataMember] public CodeStyleOption2 NamespaceDeclarations { get; init; } = s_blockedScopedWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferTrailingComma { get; init; } = s_trueWithSuggestionEnforcement; public override bool Equals(object? obj) => Equals(obj as CSharpCodeGenerationOptions); @@ -62,7 +63,8 @@ public bool Equals(CSharpCodeGenerationOptions? other) PreferExpressionBodiedLocalFunctions.Equals(other.PreferExpressionBodiedLocalFunctions) && PreferExpressionBodiedLambdas.Equals(other.PreferExpressionBodiedLambdas) && PreferStaticLocalFunction.Equals(other.PreferStaticLocalFunction) && - NamespaceDeclarations.Equals(other.NamespaceDeclarations); + NamespaceDeclarations.Equals(other.NamespaceDeclarations) && + PreferTrailingComma.Equals(other.PreferTrailingComma); public override int GetHashCode() => Hash.Combine(Common, From d06994cf71b1d8c8d6986c1870a755838d9c19c3 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 24 Jun 2022 09:45:51 +0200 Subject: [PATCH 11/29] Delete CSharpCodeGenerationPreferences.cs --- .../CSharpCodeGenerationPreferences.cs | 79 ------------------- 1 file changed, 79 deletions(-) delete mode 100644 src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs deleted file mode 100644 index 5adef926cf4bf..0000000000000 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationPreferences.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.AddImport; -using Microsoft.CodeAnalysis.CodeGeneration; -using Microsoft.CodeAnalysis.CodeStyle; -using Microsoft.CodeAnalysis.CSharp.CodeStyle; -using Microsoft.CodeAnalysis.Options; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.CSharp.CodeGeneration -{ - internal sealed class CSharpCodeGenerationPreferences : CodeGenerationPreferences - { - public readonly LanguageVersion LanguageVersion; - - public CSharpCodeGenerationPreferences(CSharpParseOptions parseOptions, OptionSet options) - : this(parseOptions.LanguageVersion, options) - { - } - - public CSharpCodeGenerationPreferences(LanguageVersion languageVersion, OptionSet options) - : base(options) - { - LanguageVersion = languageVersion; - } - - public ExpressionBodyPreference PreferExpressionBodiedMethods - => Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value; - - public ExpressionBodyPreference PreferExpressionBodiedAccessors - => Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value; - - public ExpressionBodyPreference PreferExpressionBodiedProperties - => Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value; - - public ExpressionBodyPreference PreferExpressionBodiedIndexers - => Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers).Value; - - public ExpressionBodyPreference PreferExpressionBodiedConstructors - => Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors).Value; - - public ExpressionBodyPreference PreferExpressionBodiedOperators - => Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value; - - public ExpressionBodyPreference PreferExpressionBodiedLocalFunctions - => Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions).Value; - - public NamespaceDeclarationPreference NamespaceDeclarations - => Options.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations).Value; - - public AddImportPlacement PreferredUsingDirectivePlacement - => Options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement).Value; - - public bool PreferTrailingComma - => Options.GetOption(CSharpCodeStyleOptions.PreferTrailingComma).Value; - - public override bool PlaceImportsInsideNamespaces - => PreferredUsingDirectivePlacement == AddImportPlacement.InsideNamespace; - - public override string Language - => LanguageNames.CSharp; - - public override CodeGenerationOptions GetOptions(CodeGenerationContext context) - => new CSharpCodeGenerationOptions(context, this); - - public static new async Task FromDocumentAsync(Document document, CancellationToken cancellationToken) - { - var parseOptions = (CSharpParseOptions?)document.Project.ParseOptions; - Contract.ThrowIfNull(parseOptions); - - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return new CSharpCodeGenerationPreferences(parseOptions, documentOptions); - } - } -} From 3d0270ac0215882c5aa9bb7172b4e424c6f763f8 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 24 Jun 2022 09:47:52 +0200 Subject: [PATCH 12/29] Update CSharpCodeGenerationOptions.cs --- .../CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs index 38006b09cef24..dfcd3b49e0fa9 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs @@ -77,7 +77,7 @@ public override int GetHashCode() Hash.Combine(PreferExpressionBodiedLocalFunctions, Hash.Combine(PreferExpressionBodiedLambdas, Hash.Combine(PreferStaticLocalFunction, - Hash.Combine(NamespaceDeclarations, 0))))))))))); + Hash.Combine(NamespaceDeclarations, PreferTrailingComma))))))))))); #if !CODE_STYLE public override CodeGenerationContextInfo GetInfo(CodeGenerationContext context, ParseOptions parseOptions) @@ -103,7 +103,8 @@ public static CSharpCodeGenerationOptions GetCSharpCodeGenerationOptions(this An PreferExpressionBodiedLocalFunctions = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, fallbackOptions.PreferExpressionBodiedLocalFunctions), PreferExpressionBodiedLambdas = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas, fallbackOptions.PreferExpressionBodiedLambdas), PreferStaticLocalFunction = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferStaticLocalFunction, fallbackOptions.PreferStaticLocalFunction), - NamespaceDeclarations = options.GetEditorConfigOption(CSharpCodeStyleOptions.NamespaceDeclarations, fallbackOptions.NamespaceDeclarations) + NamespaceDeclarations = options.GetEditorConfigOption(CSharpCodeStyleOptions.NamespaceDeclarations, fallbackOptions.NamespaceDeclarations), + PreferTrailingComma = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferTrailingComma, fallbackOptions.PreferTrailingComma), }; } } From acdcbdbbeaa64e6f235aa9e6b6a97ea66165dd87 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 24 Jun 2022 11:49:12 +0200 Subject: [PATCH 13/29] Few fixes --- .../Analyzers/CSharpAnalyzers.projitems | 1 + .../CSharpAnalyzerOptionsProvider.cs | 1 + .../PreferTrailingCommaDiagnosticAnalyzer.cs | 62 ++++++++++++++++ .../Tests/CSharpAnalyzers.UnitTests.projitems | 1 + .../PreferTrailingCommaTests.cs | 74 +++++++++++++++++++ .../Core/Analyzers/EnforceOnBuildValues.cs | 1 + .../Core/Analyzers/IDEDiagnosticIds.cs | 2 + .../CSharpSimplifierOptionsStorage.cs | 1 + .../Simplification/CSharpSimplifierOptions.cs | 10 ++- 9 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs create mode 100644 src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs diff --git a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems index 7cb7c5863c94c..95e56c32d68ec 100644 --- a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems +++ b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems @@ -34,6 +34,7 @@ + diff --git a/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs b/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs index ab7ce1d7cff07..750b73936918d 100644 --- a/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs +++ b/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs @@ -50,6 +50,7 @@ public CSharpAnalyzerOptionsProvider(AnalyzerConfigOptions options, AnalyzerOpti public CodeStyleOption2 AllowEmbeddedStatementsOnSameLine => GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine, FallbackSimplifierOptions.AllowEmbeddedStatementsOnSameLine); public CodeStyleOption2 PreferThrowExpression => GetOption(CSharpCodeStyleOptions.PreferThrowExpression, FallbackSimplifierOptions.PreferThrowExpression); public CodeStyleOption2 PreferBraces => GetOption(CSharpCodeStyleOptions.PreferBraces, FallbackSimplifierOptions.PreferBraces); + public CodeStyleOption2 PreferTrailingComma => GetOption(CSharpCodeStyleOptions.PreferTrailingComma, FallbackSimplifierOptions.PreferTrailingComma); internal CSharpSimplifierOptions GetSimplifierOptions() => _options.GetCSharpSimplifierOptions(FallbackSimplifierOptions); diff --git a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000..b2698a897789c --- /dev/null +++ b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.PreferTrailingComma +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal sealed class PreferTrailingCommaDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer + { + public PreferTrailingCommaDiagnosticAnalyzer() : base( + diagnosticId: IDEDiagnosticIds.PreferTrailingCommaDiagnosticId, + enforceOnBuild: EnforceOnBuildValues.PreferTrailingComma, + option: CSharpCodeStyleOptions.PreferTrailingComma, + language: LanguageNames.CSharp, + title: new LocalizableResourceString(nameof(CSharpAnalyzersResources.Convert_to_Program_Main_style_program), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) + { + } + public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SyntaxTreeWithoutSemanticsAnalysis; + + protected override void InitializeWorker(AnalysisContext context) + { + // enum members + // list patterns + // property pattern + // anonymous object creation + // initializer expression + // switch expression + context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.EnumDeclaration); + } + + private static void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) + { + var option = context.GetCSharpAnalyzerOptions().PreferTrailingComma; + if (!option.Value) + return; + + var node = context.Node; + switch (node) + { + case EnumDeclarationSyntax enumDeclaration: + AnalyzeEnumDeclaration(enumDeclaration); + break; + default: + throw ExceptionUtilities.Unreachable; + } + } + + private static void AnalyzeEnumDeclaration(EnumDeclarationSyntax enumDeclaration) + { + var members = enumDeclaration.Members; + } + } +} diff --git a/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems b/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems index 775028d3d2390..52854744b453d 100644 --- a/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems +++ b/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems @@ -29,6 +29,7 @@ + diff --git a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs new file mode 100644 index 0000000000000..27970646dfbea --- /dev/null +++ b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.PreferTrailingComma; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.Analyzers.UnitTests.PreferTrailingComma +{ + using VerifyCS = CSharpCodeFixVerifier; /* PROTOTYPE: Implement codefix. */ + + public class PreferTrailingCommaTests + { + [Fact] + public async Task TestOptionOff() + { + await new VerifyCS.Test + { + TestState = + { + Sources = + { + @"enum A +{ + A, + B +}", + }, + AnalyzerConfigFiles = + { + ("/.editorconfig", @"[*] +csharp_style_prefer_trailing_comma = false"), + }, + }, + }.RunAsync(); + } + + [Fact] + public async Task TestOptionOn() + { + await new VerifyCS.Test + { + TestState = + { + Sources = + { + @"enum A +{ + A, + [|B|] +} +", + }, + AnalyzerConfigFiles = + { + ("/.editorconfig", @"[*] +csharp_style_prefer_trailing_comma = true") + }, + }, + FixedCode = @"enum A +{ + A, + B, +} +" + }.RunAsync(); + } + } +} diff --git a/src/Analyzers/Core/Analyzers/EnforceOnBuildValues.cs b/src/Analyzers/Core/Analyzers/EnforceOnBuildValues.cs index 0f3b05bb14276..fcf3e4744680a 100644 --- a/src/Analyzers/Core/Analyzers/EnforceOnBuildValues.cs +++ b/src/Analyzers/Core/Analyzers/EnforceOnBuildValues.cs @@ -29,6 +29,7 @@ internal static class EnforceOnBuildValues public const EnforceOnBuild UseBlockScopedNamespace = /*IDE0160*/ EnforceOnBuild.HighlyRecommended; public const EnforceOnBuild UseFileScopedNamespace = /*IDE0161*/ EnforceOnBuild.HighlyRecommended; public const EnforceOnBuild UseTupleSwap = /*IDE0180*/ EnforceOnBuild.HighlyRecommended; + public const EnforceOnBuild PreferTrailingComma = /*IDE0250*/ EnforceOnBuild.HighlyRecommended; /* EnforceOnBuild.Recommended */ public const EnforceOnBuild UseThrowExpression = /*IDE0016*/ EnforceOnBuild.Recommended; diff --git a/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs b/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs index 5a44b570963b6..3aea2dc2a4670 100644 --- a/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs +++ b/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs @@ -181,6 +181,8 @@ internal static class IDEDiagnosticIds public const string RemoveRedundantNullableDirectiveDiagnosticId = "IDE0240"; public const string RemoveUnnecessaryNullableDirectiveDiagnosticId = "IDE0241"; + public const string PreferTrailingCommaDiagnosticId = "IDE0250"; + // Analyzer error Ids public const string AnalyzerChangedId = "IDE1001"; public const string AnalyzerDependencyConflictId = "IDE1002"; diff --git a/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs b/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs index e5dec6cf5fd97..5e361b9705886 100644 --- a/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs +++ b/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs @@ -38,5 +38,6 @@ public static CSharpSimplifierOptions GetCSharpSimplifierOptions(this IGlobalOpt AllowEmbeddedStatementsOnSameLine = globalOptions.GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine), PreferBraces = globalOptions.GetOption(CSharpCodeStyleOptions.PreferBraces), PreferThrowExpression = globalOptions.GetOption(CSharpCodeStyleOptions.PreferThrowExpression), + PreferTrailingComma = globalOptions.GetOption(CSharpCodeStyleOptions.PreferTrailingComma), }; } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs index 5d726afe1e390..5852f39862d03 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs @@ -36,6 +36,7 @@ internal sealed class CSharpSimplifierOptions : SimplifierOptions, IEquatable AllowEmbeddedStatementsOnSameLine { get; init; } = s_trueWithSilentEnforcement; [DataMember] public CodeStyleOption2 PreferBraces { get; init; } = s_defaultPreferBraces; [DataMember] public CodeStyleOption2 PreferThrowExpression { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferTrailingComma { get; init; } = s_trueWithSuggestionEnforcement; public override bool Equals(object? obj) => Equals(obj as CSharpSimplifierOptions); @@ -50,7 +51,8 @@ public bool Equals([AllowNull] CSharpSimplifierOptions other) PreferParameterNullChecking.Equals(other.PreferParameterNullChecking) && AllowEmbeddedStatementsOnSameLine.Equals(other.AllowEmbeddedStatementsOnSameLine) && PreferBraces.Equals(other.PreferBraces) && - PreferThrowExpression.Equals(other.PreferThrowExpression); + PreferThrowExpression.Equals(other.PreferThrowExpression) && + PreferTrailingComma.Equals(other.PreferTrailingComma); public override int GetHashCode() => Hash.Combine(VarForBuiltInTypes, @@ -60,7 +62,8 @@ public override int GetHashCode() Hash.Combine(PreferParameterNullChecking, Hash.Combine(AllowEmbeddedStatementsOnSameLine, Hash.Combine(PreferBraces, - Hash.Combine(PreferThrowExpression, 0)))))))); + Hash.Combine(PreferThrowExpression, + Hash.Combine(PreferTrailingComma, 0))))))))); } internal static class CSharpSimplifierOptionsProviders @@ -78,7 +81,8 @@ public static CSharpSimplifierOptions GetCSharpSimplifierOptions(this AnalyzerCo PreferSimpleDefaultExpression = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression, fallbackOptions.PreferSimpleDefaultExpression), AllowEmbeddedStatementsOnSameLine = options.GetEditorConfigOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine, fallbackOptions.AllowEmbeddedStatementsOnSameLine), PreferBraces = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferBraces, fallbackOptions.PreferBraces), - PreferThrowExpression = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferThrowExpression, fallbackOptions.PreferThrowExpression) + PreferThrowExpression = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferThrowExpression, fallbackOptions.PreferThrowExpression), + PreferTrailingComma = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferTrailingComma, fallbackOptions.PreferTrailingComma), }; } } From b776b61c06ed64066d4b5192010bf83986005872 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 24 Jun 2022 13:35:10 +0200 Subject: [PATCH 14/29] Code fix --- .../Analyzers/CSharpAnalyzersResources.resx | 3 + .../PreferTrailingCommaDiagnosticAnalyzer.cs | 28 +++++++-- .../xlf/CSharpAnalyzersResources.cs.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.de.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.es.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.fr.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.it.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.ja.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.ko.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.pl.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.pt-BR.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.ru.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.tr.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.zh-Hans.xlf | 5 ++ .../xlf/CSharpAnalyzersResources.zh-Hant.xlf | 5 ++ .../CodeFixes/CSharpCodeFixes.projitems | 1 + .../PreferTrailingCommaCodeFixProvider.cs | 58 +++++++++++++++++++ .../PreferTrailingCommaTests.cs | 50 +++++++++++++++- .../PredefinedCodeFixProviderNames.cs | 1 + .../CSharpCodeGenerationOptions.cs | 3 +- 20 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs diff --git a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzersResources.resx b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzersResources.resx index 05da91a8cd025..cae5800f64740 100644 --- a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzersResources.resx +++ b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzersResources.resx @@ -383,4 +383,7 @@ Remove redundant nullable directive + + Missing trailing comma + \ No newline at end of file diff --git a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs index b2698a897789c..a39602c8d8017 100644 --- a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs @@ -21,14 +21,15 @@ public PreferTrailingCommaDiagnosticAnalyzer() : base( enforceOnBuild: EnforceOnBuildValues.PreferTrailingComma, option: CSharpCodeStyleOptions.PreferTrailingComma, language: LanguageNames.CSharp, - title: new LocalizableResourceString(nameof(CSharpAnalyzersResources.Convert_to_Program_Main_style_program), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) + title: new LocalizableResourceString(nameof(CSharpAnalyzersResources.Missing_trailing_comma), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) { } + public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SyntaxTreeWithoutSemanticsAnalysis; protected override void InitializeWorker(AnalysisContext context) { - // enum members + // TODO: // list patterns // property pattern // anonymous object creation @@ -37,7 +38,7 @@ protected override void InitializeWorker(AnalysisContext context) context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.EnumDeclaration); } - private static void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) + private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) { var option = context.GetCSharpAnalyzerOptions().PreferTrailingComma; if (!option.Value) @@ -47,16 +48,31 @@ private static void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) switch (node) { case EnumDeclarationSyntax enumDeclaration: - AnalyzeEnumDeclaration(enumDeclaration); + AnalyzeEnumDeclaration(context, enumDeclaration, option.Notification.Severity); break; default: throw ExceptionUtilities.Unreachable; } } - private static void AnalyzeEnumDeclaration(EnumDeclarationSyntax enumDeclaration) + private void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context, EnumDeclarationSyntax enumDeclaration, ReportDiagnostic severity) { - var members = enumDeclaration.Members; + var nodesWithSeparators = enumDeclaration.Members.GetWithSeparators(); + if (nodesWithSeparators.Count < 1) + { + return; + } + + var lastNodeOrSeparator = nodesWithSeparators[^1]; + if (lastNodeOrSeparator.IsToken) + { + return; + } + + if (lastNodeOrSeparator.IsNode) + { + context.ReportDiagnostic(DiagnosticHelper.Create(Descriptor, lastNodeOrSeparator.AsNode()!.GetLocation(), severity, additionalLocations: null, properties: null)); + } } } } diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf index a5c37de34c76e..2e14d482eaad3 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf @@ -87,6 +87,11 @@ Nesprávné umístění direktivy using {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Přesunout nesprávně umístěné direktivy using diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf index 6b2db22d01e8f..4af208032865f 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf @@ -87,6 +87,11 @@ Die using-Anweisung wurde falsch platziert. {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Falsch platzierte using-Anweisungen verschieben diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf index 8c0afdee0ad72..29539d8cd46af 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf @@ -87,6 +87,11 @@ Directiva using mal colocada {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Mover directivas using mal colocadas diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf index acac70b453687..dd73f5085864d 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf @@ -87,6 +87,11 @@ Directive using mal placée {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Déplacer les directives using mal placées diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf index 435c54e402b82..c92b83f4554e2 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf @@ -87,6 +87,11 @@ Direttiva using in posizione errata {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Sposta le direttive using in posizione errata diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf index ffea0526d74d9..41c37aeb43be7 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf @@ -87,6 +87,11 @@ using ディレクティブが正しく配置されていません {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives 誤って配置された using ディレクティブを移動します diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf index 6738cd8368b24..0adb9d0b41458 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf @@ -87,6 +87,11 @@ 위치가 잘못된 using 지시문 {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives 위치가 잘못된 using 지시문 이동 diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf index f2d3f2b19ef53..6f7d3475fcafc 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf @@ -87,6 +87,11 @@ Nieprawidłowo umieszczona dyrektywa using {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Przenieś nieprawidłowo umieszczone dyrektywy using diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf index 3a1c3bf8138d9..1f697cf8367f3 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf @@ -87,6 +87,11 @@ Diretiva using em local incorreto {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Mover diretivas using no local incorreto diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf index 90c6379ba94fe..7c1e62975afd2 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf @@ -87,6 +87,11 @@ Неправильно расположенная директива using {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Переместить неправильно расположенные директивы using diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf index 031679abc1918..ad18b9561f6fd 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf @@ -87,6 +87,11 @@ Yanlış yerleştirilmiş using yönergesi {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives Yanlış yerleştirilmiş using yönergelerini taşı diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf index feb074e0d5524..1e9959676e436 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf @@ -87,6 +87,11 @@ 错放了 using 指令 {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives 移动错放的 using 指令 diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf index 35924b6c1a6e6..d606f8cfeb094 100644 --- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf +++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf @@ -87,6 +87,11 @@ using 指示詞位置錯誤 {Locked="using"} "using" is a C# keyword and should not be localized. + + Missing trailing comma + Missing trailing comma + + Move misplaced using directives 移動位置錯誤的 using 指示詞 diff --git a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems index 1ba83cd6e3f1a..170fb4680a161 100644 --- a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems +++ b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems @@ -38,6 +38,7 @@ + diff --git a/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs new file mode 100644 index 0000000000000..3781d9e6cca74 --- /dev/null +++ b/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Immutable; +using System.Composition; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.CSharp.PreferTrailingComma +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.PreferTrailingComma), Shared] + internal sealed class PreferTrailingCommaCodeFixProvider : SyntaxEditorBasedCodeFixProvider + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public PreferTrailingCommaCodeFixProvider() + { + } + + public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(IDEDiagnosticIds.PreferTrailingCommaDiagnosticId); + + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + foreach (var diagnostic in context.Diagnostics) + RegisterCodeFix(context, "", "", diagnostic); + + return Task.CompletedTask; + } + + protected override Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) + { + foreach (var diagnostic in diagnostics) + { + var node = diagnostic.Location.FindNode(cancellationToken).Parent; + if (node is EnumDeclarationSyntax enumDeclaration) + { + var nodesAndTokens = enumDeclaration.Members.GetWithSeparators(); + var lastNode = nodesAndTokens[^1]; + nodesAndTokens = nodesAndTokens.ReplaceRange(lastNode, ImmutableArray.Create(lastNode.WithTrailingTrivia(), SyntaxFactory.Token(leading: default, SyntaxKind.CommaToken, trailing: lastNode.GetTrailingTrivia()))); + var newEnumDeclaration = enumDeclaration.WithMembers(SyntaxFactory.SeparatedList(nodesAndTokens)); + editor.ReplaceNode(enumDeclaration, newEnumDeclaration); + } + } + + return Task.CompletedTask; + } + } +} diff --git a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs index 27970646dfbea..6aed27dce7759 100644 --- a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs +++ b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Analyzers.UnitTests.PreferTrailingComma { - using VerifyCS = CSharpCodeFixVerifier; /* PROTOTYPE: Implement codefix. */ + using VerifyCS = CSharpCodeFixVerifier; public class PreferTrailingCommaTests { @@ -70,5 +70,53 @@ public async Task TestOptionOn() " }.RunAsync(); } + + [Fact] + public async Task TestHasTrailingComma() + { + var code = @"enum A +{ + A, + B, +} +"; + await VerifyCS.VerifyCodeFixAsync(code, code); + } + + [Fact] + public async Task TestTriviaOnEnumMember() + { + var code = @"enum A +{ + A, + // comment 1 + [|B|] // comment 2 +} +"; + var fixedCode = @"enum A +{ + A, + // comment 1 + B, // comment 2 +} +"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [Fact] + public async Task TestEnumMemberOnSameLine() + { + var code = @"enum A +{ + A, [|B|] // comment +} +"; + var fixedCode = @"enum A +{ + A, B, // comment +} +"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } } } diff --git a/src/Analyzers/Core/CodeFixes/PredefinedCodeFixProviderNames.cs b/src/Analyzers/Core/CodeFixes/PredefinedCodeFixProviderNames.cs index 0561ae2c91daa..071d2daf10f97 100644 --- a/src/Analyzers/Core/CodeFixes/PredefinedCodeFixProviderNames.cs +++ b/src/Analyzers/Core/CodeFixes/PredefinedCodeFixProviderNames.cs @@ -158,5 +158,6 @@ internal static class PredefinedCodeFixProviderNames public const string UseThrowExpression = nameof(UseThrowExpression); public const string UseTupleSwap = nameof(UseTupleSwap); public const string UseUTF8StringLiteral = nameof(UseUTF8StringLiteral); + public const string PreferTrailingComma = nameof(PreferTrailingComma); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs index dfcd3b49e0fa9..472c46c491220 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs @@ -77,7 +77,8 @@ public override int GetHashCode() Hash.Combine(PreferExpressionBodiedLocalFunctions, Hash.Combine(PreferExpressionBodiedLambdas, Hash.Combine(PreferStaticLocalFunction, - Hash.Combine(NamespaceDeclarations, PreferTrailingComma))))))))))); + Hash.Combine(NamespaceDeclarations, + Hash.Combine(PreferTrailingComma, 0)))))))))))); #if !CODE_STYLE public override CodeGenerationContextInfo GetInfo(CodeGenerationContext context, ParseOptions parseOptions) From 64972d8b10c439236874ff60e762e075459ada1f Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 24 Jun 2022 14:37:41 +0200 Subject: [PATCH 15/29] More progress --- .../PreferTrailingCommaDiagnosticAnalyzer.cs | 29 ++++--- .../PreferTrailingCommaCodeFixProvider.cs | 25 +++--- .../PreferTrailingCommaTests.cs | 78 +++++++++++++++++++ 3 files changed, 107 insertions(+), 25 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs index a39602c8d8017..adef1fad33c9d 100644 --- a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs @@ -35,7 +35,7 @@ protected override void InitializeWorker(AnalysisContext context) // anonymous object creation // initializer expression // switch expression - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.EnumDeclaration); + context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.EnumDeclaration, SyntaxKind.PropertyPatternClause); } private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) @@ -44,20 +44,7 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) if (!option.Value) return; - var node = context.Node; - switch (node) - { - case EnumDeclarationSyntax enumDeclaration: - AnalyzeEnumDeclaration(context, enumDeclaration, option.Notification.Severity); - break; - default: - throw ExceptionUtilities.Unreachable; - } - } - - private void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context, EnumDeclarationSyntax enumDeclaration, ReportDiagnostic severity) - { - var nodesWithSeparators = enumDeclaration.Members.GetWithSeparators(); + var nodesWithSeparators = GetNodesWithSeparators(context.Node); if (nodesWithSeparators.Count < 1) { return; @@ -71,8 +58,18 @@ private void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context, EnumDecla if (lastNodeOrSeparator.IsNode) { - context.ReportDiagnostic(DiagnosticHelper.Create(Descriptor, lastNodeOrSeparator.AsNode()!.GetLocation(), severity, additionalLocations: null, properties: null)); + context.ReportDiagnostic(DiagnosticHelper.Create(Descriptor, lastNodeOrSeparator.AsNode()!.GetLocation(), option.Notification.Severity, additionalLocations: null, properties: null)); } } + + internal static SyntaxNodeOrTokenList GetNodesWithSeparators(SyntaxNode node) + { + return node switch + { + EnumDeclarationSyntax enumDeclaration => enumDeclaration.Members.GetWithSeparators(), + PropertyPatternClauseSyntax propertyPattern => propertyPattern.Subpatterns.GetWithSeparators(), + _ => throw ExceptionUtilities.Unreachable, + }; + } } } diff --git a/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs index 3781d9e6cca74..3a2a86192edba 100644 --- a/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.Extensions; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.PreferTrailingComma { @@ -41,18 +42,24 @@ protected override Task FixAllAsync(Document document, ImmutableArray(nodesAndTokens)); - editor.ReplaceNode(enumDeclaration, newEnumDeclaration); - } + var node = diagnostic.Location.FindNode(cancellationToken).GetRequiredParent(); + var nodesAndTokens = PreferTrailingCommaDiagnosticAnalyzer.GetNodesWithSeparators(node); + var lastNode = nodesAndTokens[^1]; + nodesAndTokens = nodesAndTokens.ReplaceRange(lastNode, ImmutableArray.Create(lastNode.WithTrailingTrivia(), SyntaxFactory.Token(leading: default, SyntaxKind.CommaToken, trailing: lastNode.GetTrailingTrivia()))); + editor.ReplaceNode(node, GetReplacement(node, nodesAndTokens)); } return Task.CompletedTask; } + + private static SyntaxNode GetReplacement(SyntaxNode node, SyntaxNodeOrTokenList nodesAndTokens) + { + return node switch + { + EnumDeclarationSyntax enumDeclaration => enumDeclaration.WithMembers(SyntaxFactory.SeparatedList(nodesAndTokens)), + PropertyPatternClauseSyntax propertyPattern => propertyPattern.WithSubpatterns(SyntaxFactory.SeparatedList(nodesAndTokens)), + _ => throw ExceptionUtilities.Unreachable, + }; + } } } diff --git a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs index 6aed27dce7759..1aae5ef4f841e 100644 --- a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs +++ b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs @@ -115,6 +115,84 @@ public async Task TestEnumMemberOnSameLine() { A, B, // comment } +"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [Fact] + public async Task TestPropertyPattern() + { + var code = @"class C +{ + void M(string s) + { + if (s is { Length: 0, [|Length: 0|] }) + { + } + } +} +"; + var fixedCode = @"class C +{ + void M(string s) + { + if (s is { Length: 0, Length: 0, }) + { + } + } +} +"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [Fact] + public async Task TestPropertyPatternHasTrailingComma() + { + var code = @"class C +{ + void M(string s) + { + if (s is { Length: 0, Length: 0, }) + { + } + } +} +"; + await VerifyCS.VerifyCodeFixAsync(code, code); + } + + [Fact] + public async Task TestTriviaOnPropertyPattern() + { + var code = @"class C +{ + void M(string s) + { + if (s is + { + Length: 0, + // comment 1 + [|Length: 0|] // comment 2 + }) + { + } + } +} +"; + var fixedCode = @"class C +{ + void M(string s) + { + if (s is + { + Length: 0, + // comment 1 + Length: 0, // comment 2 + }) + { + } + } +} "; await VerifyCS.VerifyCodeFixAsync(code, fixedCode); } From cb0ae2b922a12b8d49f7d2a0a065c2cd7cdd51a8 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 24 Jun 2022 15:06:58 +0200 Subject: [PATCH 16/29] Adjust implementation --- .../PreferTrailingCommaDiagnosticAnalyzer.cs | 16 +++++++-- .../PreferTrailingCommaTests.cs | 34 +++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs index adef1fad33c9d..f3ebf951256e0 100644 --- a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; +using System.Threading; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -31,7 +33,6 @@ protected override void InitializeWorker(AnalysisContext context) { // TODO: // list patterns - // property pattern // anonymous object creation // initializer expression // switch expression @@ -58,10 +59,21 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) if (lastNodeOrSeparator.IsNode) { - context.ReportDiagnostic(DiagnosticHelper.Create(Descriptor, lastNodeOrSeparator.AsNode()!.GetLocation(), option.Notification.Severity, additionalLocations: null, properties: null)); + var lastNode = lastNodeOrSeparator.AsNode()!; + if (CommaWillBeLastTokenOnLine(lastNode, context.CancellationToken)) + context.ReportDiagnostic(DiagnosticHelper.Create(Descriptor, lastNode.GetLocation(), option.Notification.Severity, additionalLocations: null, properties: null)); } } + private static bool CommaWillBeLastTokenOnLine(SyntaxNode node, CancellationToken cancellationToken) + { + var lines = node.SyntaxTree.GetText(cancellationToken).Lines; + var lastCurrentToken = node.DescendantTokens().Last(); + var line1 = lines.GetLineFromPosition(lastCurrentToken.Span.End).LineNumber; + var line2 = lines.GetLineFromPosition(lastCurrentToken.GetNextToken().SpanStart).LineNumber; + return line1 != line2; + } + internal static SyntaxNodeOrTokenList GetNodesWithSeparators(SyntaxNode node) { return node switch diff --git a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs index 1aae5ef4f841e..581282f3d2977 100644 --- a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs +++ b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs @@ -126,7 +126,11 @@ public async Task TestPropertyPattern() { void M(string s) { - if (s is { Length: 0, [|Length: 0|] }) + if (s is + { + Length: 0, + [|Length: 0|] + }) { } } @@ -136,7 +140,11 @@ void M(string s) { void M(string s) { - if (s is { Length: 0, Length: 0, }) + if (s is + { + Length: 0, + Length: 0, + }) { } } @@ -152,7 +160,11 @@ public async Task TestPropertyPatternHasTrailingComma() { void M(string s) { - if (s is { Length: 0, Length: 0, }) + if (s is + { + Length: 0, + Length: 0, + }) { } } @@ -196,5 +208,21 @@ void M(string s) "; await VerifyCS.VerifyCodeFixAsync(code, fixedCode); } + + [Fact] + public async Task TestPropertyPatternOnSameLine() + { + var code = @"class C +{ + void M(string s) + { + if (s is { Length: 0, Length: 0 }) + { + } + } +} +"; + await VerifyCS.VerifyCodeFixAsync(code, code); + } } } From c62f3266fe39c9caa3ceac5af87d5f65d657ff4b Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 24 Jun 2022 16:10:43 +0200 Subject: [PATCH 17/29] Fix incorrectly resolved conflicts --- src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf | 3 +-- src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf | 3 +-- src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index 469d7663ecb73..34c8b7fe3a1ef 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -1126,10 +1126,9 @@ Prefer trailing comma Prefer trailing comma -======= + Prefer top-level statements Предпочитать инструкции верхнего уровня ->>>>>>> upstream/main diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index 953ce77aedf91..56b7ee0857d2a 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -1126,10 +1126,9 @@ Prefer trailing comma Prefer trailing comma -======= + Prefer top-level statements Üst düzey deyimleri tercih et ->>>>>>> upstream/main diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index 2470ecf1cec51..16fcae0c9e30f 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -1126,10 +1126,9 @@ Prefer trailing comma Prefer trailing comma -======= + Prefer top-level statements 首选顶级语句 ->>>>>>> upstream/main From c79ba3b2fc08e7000425e219cf2504d1f31a85e5 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 24 Jun 2022 16:37:13 +0200 Subject: [PATCH 18/29] Update ServicesVSResources.ru.xlf --- src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index 34c8b7fe3a1ef..ae909e866aeb9 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -1125,6 +1125,7 @@ Prefer trailing comma Prefer trailing comma + Prefer top-level statements From effe159e5bd40065b8076b391cd913a2e2aff1ee Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 24 Jun 2022 21:18:50 +0200 Subject: [PATCH 19/29] More work.. Nested diagnostics fixall is failing.. --- .../PreferTrailingCommaDiagnosticAnalyzer.cs | 20 +- .../CodeFixes/CSharpCodeFixesResources.resx | 3 + .../PreferTrailingCommaCodeFixProvider.cs | 6 +- .../xlf/CSharpCodeFixesResources.cs.xlf | 5 + .../xlf/CSharpCodeFixesResources.de.xlf | 5 + .../xlf/CSharpCodeFixesResources.es.xlf | 5 + .../xlf/CSharpCodeFixesResources.fr.xlf | 5 + .../xlf/CSharpCodeFixesResources.it.xlf | 5 + .../xlf/CSharpCodeFixesResources.ja.xlf | 5 + .../xlf/CSharpCodeFixesResources.ko.xlf | 5 + .../xlf/CSharpCodeFixesResources.pl.xlf | 5 + .../xlf/CSharpCodeFixesResources.pt-BR.xlf | 5 + .../xlf/CSharpCodeFixesResources.ru.xlf | 5 + .../xlf/CSharpCodeFixesResources.tr.xlf | 5 + .../xlf/CSharpCodeFixesResources.zh-Hans.xlf | 5 + .../xlf/CSharpCodeFixesResources.zh-Hant.xlf | 5 + .../PreferTrailingCommaTests.cs | 534 ++++++++++++++++-- .../Core/Analyzers/IDEDiagnosticIds.cs | 4 +- 18 files changed, 568 insertions(+), 64 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs index f3ebf951256e0..9cd03597e9945 100644 --- a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs @@ -31,12 +31,10 @@ public PreferTrailingCommaDiagnosticAnalyzer() : base( protected override void InitializeWorker(AnalysisContext context) { - // TODO: - // list patterns - // anonymous object creation - // initializer expression - // switch expression - context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.EnumDeclaration, SyntaxKind.PropertyPatternClause); + context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, + SyntaxKind.EnumDeclaration, SyntaxKind.PropertyPatternClause, SyntaxKind.SwitchExpression, + SyntaxKind.ObjectInitializerExpression, SyntaxKind.CollectionInitializerExpression, SyntaxKind.WithInitializerExpression, + SyntaxKind.ArrayInitializerExpression, SyntaxKind.ComplexElementInitializerExpression, SyntaxKind.AnonymousObjectCreationExpression, SyntaxKind.ListPattern); } private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) @@ -69,6 +67,12 @@ private static bool CommaWillBeLastTokenOnLine(SyntaxNode node, CancellationToke { var lines = node.SyntaxTree.GetText(cancellationToken).Lines; var lastCurrentToken = node.DescendantTokens().Last(); + var nextToken = lastCurrentToken.GetNextToken(); + if (nextToken == default) + { + return true; + } + var line1 = lines.GetLineFromPosition(lastCurrentToken.Span.End).LineNumber; var line2 = lines.GetLineFromPosition(lastCurrentToken.GetNextToken().SpanStart).LineNumber; return line1 != line2; @@ -80,6 +84,10 @@ internal static SyntaxNodeOrTokenList GetNodesWithSeparators(SyntaxNode node) { EnumDeclarationSyntax enumDeclaration => enumDeclaration.Members.GetWithSeparators(), PropertyPatternClauseSyntax propertyPattern => propertyPattern.Subpatterns.GetWithSeparators(), + SwitchExpressionSyntax switchExpression => switchExpression.Arms.GetWithSeparators(), + InitializerExpressionSyntax initializerExpression => initializerExpression.Expressions.GetWithSeparators(), + AnonymousObjectCreationExpressionSyntax anonymousObjectCreation => anonymousObjectCreation.Initializers.GetWithSeparators(), + ListPatternSyntax listPattern => listPattern.Patterns.GetWithSeparators(), _ => throw ExceptionUtilities.Unreachable, }; } diff --git a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixesResources.resx b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixesResources.resx index 7e37cbfd2dbbd..d193d776c4613 100644 --- a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixesResources.resx +++ b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixesResources.resx @@ -187,4 +187,7 @@ Declare as nullable + + Add trailing comma + \ No newline at end of file diff --git a/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs index 3a2a86192edba..d8f34b74caba4 100644 --- a/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs @@ -33,7 +33,7 @@ public PreferTrailingCommaCodeFixProvider() public override Task RegisterCodeFixesAsync(CodeFixContext context) { foreach (var diagnostic in context.Diagnostics) - RegisterCodeFix(context, "", "", diagnostic); + RegisterCodeFix(context, CSharpCodeFixesResources.Add_trailing_comma, nameof(CSharpCodeFixesResources.Add_trailing_comma), diagnostic); return Task.CompletedTask; } @@ -58,6 +58,10 @@ private static SyntaxNode GetReplacement(SyntaxNode node, SyntaxNodeOrTokenList { EnumDeclarationSyntax enumDeclaration => enumDeclaration.WithMembers(SyntaxFactory.SeparatedList(nodesAndTokens)), PropertyPatternClauseSyntax propertyPattern => propertyPattern.WithSubpatterns(SyntaxFactory.SeparatedList(nodesAndTokens)), + SwitchExpressionSyntax switchExpression => switchExpression.WithArms(SyntaxFactory.SeparatedList(nodesAndTokens)), + InitializerExpressionSyntax initializerExpression => initializerExpression.WithExpressions(SyntaxFactory.SeparatedList(nodesAndTokens)), + AnonymousObjectCreationExpressionSyntax anonymousObjectCreation => anonymousObjectCreation.WithInitializers(SyntaxFactory.SeparatedList(nodesAndTokens)), + ListPatternSyntax listPattern => listPattern.WithPatterns(SyntaxFactory.SeparatedList(nodesAndTokens)), _ => throw ExceptionUtilities.Unreachable, }; } diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.cs.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.cs.xlf index 4e992b7a672d2..15235582e312a 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.cs.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.cs.xlf @@ -17,6 +17,11 @@ Přidejte položku this. + + Add trailing comma + Add trailing comma + + Assign to '{0}' Přiřadit k {0} diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.de.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.de.xlf index 34626a07eb094..3ab3a6c53e980 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.de.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.de.xlf @@ -17,6 +17,11 @@ "this." hinzufügen + + Add trailing comma + Add trailing comma + + Assign to '{0}' "{0}" zuweisen diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.es.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.es.xlf index 8c30bd02a594d..3f9dc797a4b69 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.es.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.es.xlf @@ -17,6 +17,11 @@ Agregar "this." + + Add trailing comma + Add trailing comma + + Assign to '{0}' Asignar a "{0}" diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.fr.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.fr.xlf index 179a1a8e27920..5c2b17c50a010 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.fr.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.fr.xlf @@ -17,6 +17,11 @@ Ajouter 'this.' + + Add trailing comma + Add trailing comma + + Assign to '{0}' Affecter à '{0}' diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.it.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.it.xlf index 2254585338928..bce88a76e6636 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.it.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.it.xlf @@ -17,6 +17,11 @@ Aggiungi 'this.' + + Add trailing comma + Add trailing comma + + Assign to '{0}' Assegna a '{0}' diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ja.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ja.xlf index e86345bb4aecd..cf5b1a7d05468 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ja.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ja.xlf @@ -17,6 +17,11 @@ this' を追加します。 + + Add trailing comma + Add trailing comma + + Assign to '{0}' "{0}" に割り当て diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ko.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ko.xlf index 8c863dc730e46..591fe3c6160eb 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ko.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ko.xlf @@ -17,6 +17,11 @@ this'를 추가합니다. + + Add trailing comma + Add trailing comma + + Assign to '{0}' '{0}'에 할당 diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pl.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pl.xlf index b58e3ee562b61..b4b2c32368829 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pl.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pl.xlf @@ -17,6 +17,11 @@ Dodaj „this.” + + Add trailing comma + Add trailing comma + + Assign to '{0}' Przypisz do „{0}” diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pt-BR.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pt-BR.xlf index 929f1263cffc7..1c72fe6defb62 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pt-BR.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.pt-BR.xlf @@ -17,6 +17,11 @@ Adicionar 'isso.' + + Add trailing comma + Add trailing comma + + Assign to '{0}' Atribuir a '{0}' diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ru.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ru.xlf index 713b3835f0d50..b4bb476d4a1d6 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ru.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.ru.xlf @@ -17,6 +17,11 @@ Добавьте "this". + + Add trailing comma + Add trailing comma + + Assign to '{0}' Назначить "{0}" diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.tr.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.tr.xlf index 634d51f688cbb..730e2919fa30a 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.tr.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.tr.xlf @@ -17,6 +17,11 @@ this' ekleyin. + + Add trailing comma + Add trailing comma + + Assign to '{0}' '{0}' öğesine ata diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hans.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hans.xlf index 4b5146986cb1e..b2bbf4271524f 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hans.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hans.xlf @@ -17,6 +17,11 @@ 添加 "this." + + Add trailing comma + Add trailing comma + + Assign to '{0}' 赋值给 "{0}" diff --git a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hant.xlf b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hant.xlf index 9c04e649fea91..a9fe8d907812c 100644 --- a/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hant.xlf +++ b/src/Analyzers/CSharp/CodeFixes/xlf/CSharpCodeFixesResources.zh-Hant.xlf @@ -17,6 +17,11 @@ 新增 'this.' + + Add trailing comma + Add trailing comma + + Assign to '{0}' 指派給 '{0}' diff --git a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs index 581282f3d2977..59f9fb23631b8 100644 --- a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs +++ b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs @@ -6,8 +6,11 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.PreferTrailingComma; +using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; +using Microsoft.CodeAnalysis.Testing; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.Analyzers.UnitTests.PreferTrailingComma @@ -21,21 +24,14 @@ public async Task TestOptionOff() { await new VerifyCS.Test { - TestState = - { - Sources = - { - @"enum A + TestCode = @"enum A { A, B }", - }, - AnalyzerConfigFiles = - { - ("/.editorconfig", @"[*] -csharp_style_prefer_trailing_comma = false"), - }, + Options = + { + { CSharpCodeStyleOptions.PreferTrailingComma, false }, }, }.RunAsync(); } @@ -45,44 +41,25 @@ public async Task TestOptionOn() { await new VerifyCS.Test { - TestState = - { - Sources = - { - @"enum A + TestCode = @"enum A { A, [|B|] } ", - }, - AnalyzerConfigFiles = - { - ("/.editorconfig", @"[*] -csharp_style_prefer_trailing_comma = true") - }, - }, FixedCode = @"enum A { A, B, } -" +", + Options = + { + { CSharpCodeStyleOptions.PreferTrailingComma, true }, + }, }.RunAsync(); } - [Fact] - public async Task TestHasTrailingComma() - { - var code = @"enum A -{ - A, - B, -} -"; - await VerifyCS.VerifyCodeFixAsync(code, code); - } - [Fact] public async Task TestTriviaOnEnumMember() { @@ -119,6 +96,35 @@ public async Task TestEnumMemberOnSameLine() await VerifyCS.VerifyCodeFixAsync(code, fixedCode); } + [Fact] + public async Task TestEnumSingleLine() + { + var code = "enum A { A, B }"; + await VerifyCS.VerifyCodeFixAsync(code, code); + } + + [Fact] + public async Task TestNoNextToken() + { + var code = @"enum A +{ + A, + [|B|]{|CS1513:|}"; + var fixedCode = @"enum A +{ + A, + B,{|CS1513:|}"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [Fact] + public async Task TestNoNextToken_SingleLine() + { + var code = "enum A { A, [|B|]{|CS1513:|}"; + var fixedCode = "enum A { A, B,{|CS1513:|}"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + [Fact] public async Task TestPropertyPattern() { @@ -154,7 +160,7 @@ void M(string s) } [Fact] - public async Task TestPropertyPatternHasTrailingComma() + public async Task TestTriviaOnPropertyPattern() { var code = @"class C { @@ -163,66 +169,484 @@ void M(string s) if (s is { Length: 0, + // comment 1 + [|Length: 0|] // comment 2 + }) + { + } + } +} +"; + var fixedCode = @"class C +{ + void M(string s) + { + if (s is + { Length: 0, + // comment 1 + Length: 0, // comment 2 }) { } } } "; - await VerifyCS.VerifyCodeFixAsync(code, code); + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); } [Fact] - public async Task TestTriviaOnPropertyPattern() + public async Task TestPropertyPatternOnSameLine() { var code = @"class C { void M(string s) { - if (s is - { - Length: 0, - // comment 1 - [|Length: 0|] // comment 2 - }) + if (s is { Length: 0, Length: 0 }) { } } } +"; + await VerifyCS.VerifyCodeFixAsync(code, code); + } + + [Fact] + public async Task TestSwitchExpression() + { + var code = @"class C +{ + void M(object o) + { + _ = o switch + { + string s => 0, + [|_ => 1|] + }; + } +} "; var fixedCode = @"class C { - void M(string s) + void M(object o) { - if (s is + _ = o switch + { + string s => 0, + _ => 1, + }; + } +} +"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [Fact] + public async Task TestTriviaOnSwitchExpression() + { + var code = @"class C +{ + void M(object o) + { + _ = o switch + { + string s => 0, + // comment 1 + [|_ => 1|] // comment 2 + }; + } +} +"; + var fixedCode = @"class C +{ + void M(object o) + { + _ = o switch + { + string s => 0, + // comment 1 + _ => 1, // comment 2 + }; + } +} +"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [Fact] + public async Task TestSwitchExpressionOnSameLine() + { + var code = @"class C +{ + void M(object o) + { + _ = o switch { string s => 0, _ => 1 }; + } +} +"; + await VerifyCS.VerifyCodeFixAsync(code, code); + } + + [Fact] + public async Task TestTriviaOnInitializerExpression() + { + var code = @"using System; +using System.Collections.Generic; + +record C +{ + public int X; + public int Y; + + void M() + { + C c1 = new() + { + X = 0, + // Comment 1 + [|Y = 1|] // Comment 2 + }; + + var c2 = new C() + { + X = 0, + // Comment 3 + [|Y = 1|] // Comment 4 + }; + + var c3 = c1 with + { + X = 0, + // Comment 5 + [|Y = 1|] // Comment 6 + }; + + var arr1 = new int[] + { + 0, + // Comment 7 + [|1|] // Comment 8 + }; + + var arr2 = new[] + { + 0, + // Comment 7 + [|1|] // Comment 8 + }; + + ReadOnlySpan arr3 = stackalloc int[2] + { + 0, + // Comment 9 + [|1|] // Comment 10 + }; + + ReadOnlySpan arr4 = stackalloc[] + { + 0, + // Comment 11 + [|1|] // Comment 12 + }; + + var list = new List + { + 0, + // Comment 13 + [|1|] // Comment 14 + }; + } +} +"; + var fixedCode = @"using System; +using System.Collections.Generic; + +record C +{ + public int X; + public int Y; + + void M() + { + C c1 = new() + { + X = 0, + // Comment 1 + Y = 1, // Comment 2 + }; + + var c2 = new C() + { + X = 0, + // Comment 3 + Y = 1, // Comment 4 + }; + + var c3 = c1 with + { + X = 0, + // Comment 5 + Y = 1, // Comment 6 + }; + + var arr1 = new int[] + { + 0, + // Comment 7 + 1, // Comment 8 + }; + + var arr2 = new[] + { + 0, + // Comment 7 + 1, // Comment 8 + }; + + ReadOnlySpan arr3 = stackalloc int[2] + { + 0, + // Comment 9 + 1, // Comment 10 + }; + + ReadOnlySpan arr4 = stackalloc[] + { + 0, + // Comment 11 + 1, // Comment 12 + }; + + var list = new List + { + 0, + // Comment 13 + 1, // Comment 14 + }; + } +} +"; + await new VerifyCS.Test { - Length: 0, - // comment 1 - Length: 0, // comment 2 - }) + TestCode = code, + FixedCode = fixedCode, + LanguageVersion = LanguageVersion.CSharp9, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60, + }.RunAsync(); + } + + [Fact] + public async Task TestInitializerExpressionOnSameLine() { + var code = @"using System; +using System.Collections.Generic; + +record C +{ + public int X; + public int Y; + + void M() + { + C c1 = new() { X = 0, Y = 1 }; + + var c2 = new C() { X = 0, Y = 1 }; + + var c3 = c1 with { X = 0, Y = 1 }; + + var arr1 = new int[] { 0, 1 }; + + var arr2 = new[] { 0, 1 }; + + ReadOnlySpan arr3 = stackalloc int[2] { 0, 1 }; + + ReadOnlySpan arr4 = stackalloc[] { 0, 1 }; + + var list = new List { 0, 1 }; + } +} +"; + await new VerifyCS.Test + { + TestCode = code, + FixedCode = code, + LanguageVersion = LanguageVersion.CSharp9, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60, + }.RunAsync(); } + + [Fact] + public async Task TestComplexElementInitializerExpression() + { + var code = @"using System.Collections; + +class C : IEnumerable +{ + void M() + { + var c = new C() + { + // Comment 1 + 0, // Comment 2 + [|{ // Comment 3 + 1, // Comment 4 + [|2|] // Comment 5 + }|] // Comment 6 + // Comment 7 + }; } + + public void Add(int x) { } + public void Add(int x, int y) { } + public IEnumerator GetEnumerator() => null; +} +"; + var fixedCode = @"using System.Collections; + +class C : IEnumerable +{ + void M() + { + var c = new C() + { + // Comment 1 + 0, // Comment 2 + { // Comment 3 + 1, // Comment 4 + 2, // Comment 5 + }, // Comment 6 + // Comment 7 + }; + } + + public void Add(int x) { } + public void Add(int x, int y) { } + public IEnumerator GetEnumerator() => null; } "; await VerifyCS.VerifyCodeFixAsync(code, fixedCode); } [Fact] - public async Task TestPropertyPatternOnSameLine() + public async Task TestAnonymousObjectExpression() { var code = @"class C { - void M(string s) + void M() { - if (s is { Length: 0, Length: 0 }) + var c = new + { + A = 0, + [|B = 1|] + }; + } +} +"; + var fixedCode = @"class C +{ + void M() + { + var c = new + { + A = 0, + B = 1, + }; + } +} +"; + await VerifyCS.VerifyCodeFixAsync(code, fixedCode); + } + + [Fact] + public async Task TestListPattern() + { + var code = @"class C +{ + void M(object[] arr) + { + if (arr is + [ + 1, + .., + [|2|] + ]) { } } } "; - await VerifyCS.VerifyCodeFixAsync(code, code); + var fixedCode = @"class C +{ + void M(object[] arr) + { + if (arr is + [ + 1, + .., + 2, + ]) + { + } + } +} +"; + await new VerifyCS.Test + { + TestCode = code, + FixedCode = fixedCode, + LanguageVersion = LanguageVersionExtensions.CSharpNext, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60, + }.RunAsync(); + } + + [Fact] + public async Task TestListPattern_Nested() + { + var code = @"class C +{ + void M(object[][] arr) + { + if (arr is + [ + [ + [|0|] + ], + .., + [|[ + [|0|] + ]|] + ]) + { + } + } +} +"; + var fixedCode = @"class C +{ + void M(object[][] arr) + { + if (arr is + [ + [ + 0, + ], + .., + [ + 0, + ], + ]) + { + } + } +} +"; + await new VerifyCS.Test + { + TestCode = code, + FixedCode = fixedCode, + LanguageVersion = LanguageVersionExtensions.CSharpNext, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60, + }.RunAsync(); } } } diff --git a/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs b/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs index 3aea2dc2a4670..6b6913a6ad453 100644 --- a/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs +++ b/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs @@ -146,6 +146,8 @@ internal static class IDEDiagnosticIds public const string UseNotPatternDiagnosticId = "IDE0083"; public const string UseIsNotExpressionDiagnosticId = "IDE0084"; + public const string PreferTrailingCommaDiagnosticId = "IDE0085"; + public const string UseImplicitObjectCreationDiagnosticId = "IDE0090"; public const string RemoveRedundantEqualityDiagnosticId = "IDE0100"; @@ -181,8 +183,6 @@ internal static class IDEDiagnosticIds public const string RemoveRedundantNullableDirectiveDiagnosticId = "IDE0240"; public const string RemoveUnnecessaryNullableDirectiveDiagnosticId = "IDE0241"; - public const string PreferTrailingCommaDiagnosticId = "IDE0250"; - // Analyzer error Ids public const string AnalyzerChangedId = "IDE1001"; public const string AnalyzerDependencyConflictId = "IDE1002"; From cc0e20af36ad5918361796a3b9f03f8b1aaae0ec Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 24 Jun 2022 21:29:45 +0200 Subject: [PATCH 20/29] Add empty enum test --- .../PreferTrailingComma/PreferTrailingCommaTests.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs index 59f9fb23631b8..758907cf0dea1 100644 --- a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs +++ b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs @@ -103,6 +103,16 @@ public async Task TestEnumSingleLine() await VerifyCS.VerifyCodeFixAsync(code, code); } + [Fact] + public async Task TestEmptyEnum() + { + var code = @"enum A +{ +} +"; + await VerifyCS.VerifyCodeFixAsync(code, code); + } + [Fact] public async Task TestNoNextToken() { From cce88bec32604422d6c3fbc51b1d40f1e5be9dd3 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 24 Jun 2022 21:32:57 +0200 Subject: [PATCH 21/29] Update ServicesVSResources.tr.xlf --- src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index 56b7ee0857d2a..dc2629fc2bc1f 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -1125,6 +1125,7 @@ Prefer trailing comma Prefer trailing comma + Prefer top-level statements From b317c71f19b414e72bab21572cec617c4245f0bb Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Fri, 24 Jun 2022 22:13:23 +0200 Subject: [PATCH 22/29] Update ServicesVSResources.zh-Hans.xlf --- src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index 16fcae0c9e30f..cb90037be33fa 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -1125,6 +1125,7 @@ Prefer trailing comma Prefer trailing comma + Prefer top-level statements From 84b10869055c1806582a8f6d9e1b0d412fd4d0d9 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 25 Jun 2022 12:04:02 +0200 Subject: [PATCH 23/29] Fix failing tests --- .../PreferTrailingCommaDiagnosticAnalyzer.cs | 2 +- .../PreferTrailingCommaCodeFixProvider.cs | 14 +++++++++----- .../PreferTrailingCommaTests.cs | 6 ++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs index 9cd03597e9945..8e07fb55869e7 100644 --- a/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/PreferTrailingComma/PreferTrailingCommaDiagnosticAnalyzer.cs @@ -34,7 +34,7 @@ protected override void InitializeWorker(AnalysisContext context) context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.EnumDeclaration, SyntaxKind.PropertyPatternClause, SyntaxKind.SwitchExpression, SyntaxKind.ObjectInitializerExpression, SyntaxKind.CollectionInitializerExpression, SyntaxKind.WithInitializerExpression, - SyntaxKind.ArrayInitializerExpression, SyntaxKind.ComplexElementInitializerExpression, SyntaxKind.AnonymousObjectCreationExpression, SyntaxKind.ListPattern); + SyntaxKind.ArrayInitializerExpression, SyntaxKind.AnonymousObjectCreationExpression, SyntaxKind.ListPattern); } private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) diff --git a/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs index d8f34b74caba4..69063d9422260 100644 --- a/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/PreferTrailingComma/PreferTrailingCommaCodeFixProvider.cs @@ -40,20 +40,24 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) protected override Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { + // Reverse order so that we fix inner diagnostics first when there are multiple nested diagnostics. + //diagnostics = diagnostics.Sort((d1, d2) => d2.Location.SourceSpan.Start - d1.Location.SourceSpan.Start); + foreach (var diagnostic in diagnostics) { var node = diagnostic.Location.FindNode(cancellationToken).GetRequiredParent(); - var nodesAndTokens = PreferTrailingCommaDiagnosticAnalyzer.GetNodesWithSeparators(node); - var lastNode = nodesAndTokens[^1]; - nodesAndTokens = nodesAndTokens.ReplaceRange(lastNode, ImmutableArray.Create(lastNode.WithTrailingTrivia(), SyntaxFactory.Token(leading: default, SyntaxKind.CommaToken, trailing: lastNode.GetTrailingTrivia()))); - editor.ReplaceNode(node, GetReplacement(node, nodesAndTokens)); + editor.ReplaceNode(node, (n, g) => GetReplacement(n)); } return Task.CompletedTask; } - private static SyntaxNode GetReplacement(SyntaxNode node, SyntaxNodeOrTokenList nodesAndTokens) + private static SyntaxNode GetReplacement(SyntaxNode node) { + var nodesAndTokens = PreferTrailingCommaDiagnosticAnalyzer.GetNodesWithSeparators(node); + var lastNode = nodesAndTokens[^1]; + nodesAndTokens = nodesAndTokens.ReplaceRange(lastNode, ImmutableArray.Create(lastNode.WithTrailingTrivia(), SyntaxFactory.Token(leading: default, SyntaxKind.CommaToken, trailing: lastNode.GetTrailingTrivia()))); + return node switch { EnumDeclarationSyntax enumDeclaration => enumDeclaration.WithMembers(SyntaxFactory.SeparatedList(nodesAndTokens)), diff --git a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs index 758907cf0dea1..8d70192cc650c 100644 --- a/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs +++ b/src/Analyzers/CSharp/Tests/PreferTrailingComma/PreferTrailingCommaTests.cs @@ -488,6 +488,8 @@ void M() [Fact] public async Task TestComplexElementInitializerExpression() { + // At the time of writing this test, adding a comma after `2` (comment 5) doesn't compile. So ComplexElementInitializerExpression is not supported. + // If this changed in the future, the analyzer should support it. var code = @"using System.Collections; class C : IEnumerable @@ -500,7 +502,7 @@ void M() 0, // Comment 2 [|{ // Comment 3 1, // Comment 4 - [|2|] // Comment 5 + 2 // Comment 5 }|] // Comment 6 // Comment 7 }; @@ -523,7 +525,7 @@ void M() 0, // Comment 2 { // Comment 3 1, // Comment 4 - 2, // Comment 5 + 2 // Comment 5 }, // Comment 6 // Comment 7 }; From 6fa0027c672639c339542007c44e40dc24a97e13 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 25 Jun 2022 13:02:32 +0200 Subject: [PATCH 24/29] Support prefer trailing comma in use object initializer --- ...pUseObjectInitializerDiagnosticAnalyzer.cs | 5 +++ ...harpUseObjectInitializerCodeFixProvider.cs | 15 ++++---- .../UseObjectInitializerTests.cs | 34 +++++++++++++++++-- ...tUseObjectInitializerDiagnosticAnalyzer.cs | 12 ++++++- ...ractUseObjectInitializerCodeFixProvider.cs | 7 ++-- ...cUseObjectInitializerDiagnosticAnalyzer.vb | 4 +++ ...asicUseObjectInitializerCodeFixProvider.vb | 3 +- 7 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseObjectInitializer/CSharpUseObjectInitializerDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseObjectInitializer/CSharpUseObjectInitializerDiagnosticAnalyzer.cs index 935a904bc9aa7..e3802ee6de477 100644 --- a/src/Analyzers/CSharp/Analyzers/UseObjectInitializer/CSharpUseObjectInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseObjectInitializer/CSharpUseObjectInitializerDiagnosticAnalyzer.cs @@ -61,5 +61,10 @@ protected override bool IsValidContainingStatement(StatementSyntax node) return node is not LocalDeclarationStatementSyntax localDecl || localDecl.UsingKeyword == default; } + + protected override bool PreferTrailingComma(SyntaxNodeAnalysisContext context) + { + return context.GetCSharpAnalyzerOptions().PreferTrailingComma.Value; + } } } diff --git a/src/Analyzers/CSharp/CodeFixes/UseObjectInitializer/CSharpUseObjectInitializerCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseObjectInitializer/CSharpUseObjectInitializerCodeFixProvider.cs index 8ae299d393040..1b4ff75823c17 100644 --- a/src/Analyzers/CSharp/CodeFixes/UseObjectInitializer/CSharpUseObjectInitializerCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UseObjectInitializer/CSharpUseObjectInitializerCodeFixProvider.cs @@ -32,24 +32,27 @@ public CSharpUseObjectInitializerCodeFixProvider() protected override StatementSyntax GetNewStatement( StatementSyntax statement, BaseObjectCreationExpressionSyntax objectCreation, - ImmutableArray> matches) + ImmutableArray> matches, + bool addTrailingComma) { return statement.ReplaceNode( objectCreation, - GetNewObjectCreation(objectCreation, matches)); + GetNewObjectCreation(objectCreation, matches, addTrailingComma)); } private static BaseObjectCreationExpressionSyntax GetNewObjectCreation( BaseObjectCreationExpressionSyntax objectCreation, - ImmutableArray> matches) + ImmutableArray> matches, + bool addTrailingComma) { return UseInitializerHelpers.GetNewObjectCreation( - objectCreation, CreateExpressions(objectCreation, matches)); + objectCreation, CreateExpressions(objectCreation, matches, addTrailingComma)); } private static SeparatedSyntaxList CreateExpressions( BaseObjectCreationExpressionSyntax objectCreation, - ImmutableArray> matches) + ImmutableArray> matches, + bool addTrailingComma) { using var _ = ArrayBuilder.GetInstance(out var nodesAndTokens); @@ -67,7 +70,7 @@ private static SeparatedSyntaxList CreateExpressions( var newAssignment = assignment.WithLeft( match.MemberAccessExpression.Name.WithLeadingTrivia(newTrivia)); - if (i < matches.Length - 1) + if (i < matches.Length - 1 || addTrailingComma) { nodesAndTokens.Add(newAssignment); var commaToken = SyntaxFactory.Token(SyntaxKind.CommaToken) diff --git a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs index 44c5784d08172..d2f3a02dde579 100644 --- a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.UseObjectInitializer; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Test.Utilities; @@ -18,14 +19,15 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseObjectInitializer public partial class UseObjectInitializerTests { - private static async Task TestInRegularAndScriptAsync(string testCode, string fixedCode, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary) + private static async Task TestInRegularAndScriptAsync(string testCode, string fixedCode, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool preferTrailingComma = false) { await new VerifyCS.Test { TestCode = testCode, FixedCode = fixedCode, LanguageVersion = LanguageVersion.Preview, - TestState = { OutputKind = outputKind } + TestState = { OutputKind = outputKind }, + Options = { { CSharpCodeStyleOptions.PreferTrailingComma, preferTrailingComma} } }.RunAsync(); } @@ -43,6 +45,34 @@ private static async Task TestMissingInRegularAndScriptAsync(string testCode, La await test.RunAsync(); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseObjectInitializer)] + public async Task TestOnVariableDeclarator_PreferTrailingComma() + { + await TestInRegularAndScriptAsync( +@"class C +{ + int i; + + void M() + { + var c = [|new|] C(); + c.i = 1; + } +}", +@"class C +{ + int i; + + void M() + { + var c = new C + { + i = 1, + }; + } +}", preferTrailingComma: true); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseObjectInitializer)] public async Task TestOnVariableDeclarator() { diff --git a/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs index d7a659e87616c..45d78c8f53861 100644 --- a/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs @@ -29,6 +29,8 @@ internal abstract partial class AbstractUseObjectInitializerDiagnosticAnalyzer< where TAssignmentStatementSyntax : TStatementSyntax where TVariableDeclaratorSyntax : SyntaxNode { + internal const string PreferTrailingCommaKey = nameof(PreferTrailingCommaKey); + protected abstract bool FadeOutOperatorToken { get; } protected AbstractUseObjectInitializerDiagnosticAnalyzer() @@ -63,6 +65,8 @@ protected override void InitializeWorker(AnalysisContext context) protected abstract bool IsValidContainingStatement(TStatementSyntax node); + protected abstract bool PreferTrailingComma(SyntaxNodeAnalysisContext context); + private void AnalyzeNode(SyntaxNodeAnalysisContext context) { var objectCreationExpression = (TObjectCreationExpressionSyntax)context.Node; @@ -94,12 +98,18 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context) var locations = ImmutableArray.Create(objectCreationExpression.GetLocation()); + var properties = ImmutableDictionary.Empty; + if (PreferTrailingComma(context)) + { + properties = properties.Add(nameof(PreferTrailingCommaKey), ""); + } + context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, objectCreationExpression.GetFirstToken().GetLocation(), option.Notification.Severity, locations, - properties: null)); + properties: properties)); FadeOutCode(context, matches.Value, locations); } diff --git a/src/Analyzers/Core/CodeFixes/UseObjectInitializer/AbstractUseObjectInitializerCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseObjectInitializer/AbstractUseObjectInitializerCodeFixProvider.cs index ca7014e9c3c52..d3c75254b83d0 100644 --- a/src/Analyzers/Core/CodeFixes/UseObjectInitializer/AbstractUseObjectInitializerCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/UseObjectInitializer/AbstractUseObjectInitializerCodeFixProvider.cs @@ -94,8 +94,8 @@ protected override async Task FixAllAsync( var statement = objectCreation.FirstAncestorOrSelf(); Contract.ThrowIfNull(statement); - - var newStatement = GetNewStatement(statement, objectCreation, matches.Value) + const string key = AbstractUseObjectInitializerDiagnosticAnalyzer.PreferTrailingCommaKey; + var newStatement = GetNewStatement(statement, objectCreation, matches.Value, addTrailingComma: diagnostics[0].Properties.ContainsKey(key)) .WithAdditionalAnnotations(Formatter.Annotation); var subEditor = new SyntaxEditor(currentRoot, services); @@ -116,6 +116,7 @@ protected override async Task FixAllAsync( protected abstract TStatementSyntax GetNewStatement( TStatementSyntax statement, TObjectCreationExpressionSyntax objectCreation, - ImmutableArray> matches); + ImmutableArray> matches, + bool addTrailingComma); } } diff --git a/src/Analyzers/VisualBasic/Analyzers/UseObjectInitializer/VisualBasicUseObjectInitializerDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/UseObjectInitializer/VisualBasicUseObjectInitializerDiagnosticAnalyzer.vb index 73088cd3cec6d..36043aba20c45 100644 --- a/src/Analyzers/VisualBasic/Analyzers/UseObjectInitializer/VisualBasicUseObjectInitializerDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/UseObjectInitializer/VisualBasicUseObjectInitializerDiagnosticAnalyzer.vb @@ -38,5 +38,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseObjectInitializer Protected Overrides Function IsValidContainingStatement(node As StatementSyntax) As Boolean Return True End Function + + Protected Overrides Function PreferTrailingComma(context As SyntaxNodeAnalysisContext) As Boolean + Return False + End Function End Class End Namespace diff --git a/src/Analyzers/VisualBasic/CodeFixes/UseObjectInitializer/VisualBasicUseObjectInitializerCodeFixProvider.vb b/src/Analyzers/VisualBasic/CodeFixes/UseObjectInitializer/VisualBasicUseObjectInitializerCodeFixProvider.vb index 42246781a8558..7846d19d084f5 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/UseObjectInitializer/VisualBasicUseObjectInitializerCodeFixProvider.vb +++ b/src/Analyzers/VisualBasic/CodeFixes/UseObjectInitializer/VisualBasicUseObjectInitializerCodeFixProvider.vb @@ -29,7 +29,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseObjectInitializer Protected Overrides Function GetNewStatement( statement As StatementSyntax, objectCreation As ObjectCreationExpressionSyntax, - matches As ImmutableArray(Of Match(Of ExpressionSyntax, StatementSyntax, MemberAccessExpressionSyntax, AssignmentStatementSyntax))) As StatementSyntax + matches As ImmutableArray(Of Match(Of ExpressionSyntax, StatementSyntax, MemberAccessExpressionSyntax, AssignmentStatementSyntax)), + addTrailingComma As Boolean) As StatementSyntax Dim newStatement = statement.ReplaceNode( objectCreation, GetNewObjectCreation(objectCreation, matches)) From 23fa534c374e5c6d8f6f4950de54215cb2f76418 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 25 Jun 2022 13:43:11 +0200 Subject: [PATCH 25/29] Support prefer trailing comma in use collection initializer --- ...CollectionInitializerDiagnosticAnalyzer.cs | 5 +++ ...UseCollectionInitializerCodeFixProvider.cs | 15 ++++---- .../UseCollectionInitializerTests.cs | 34 +++++++++++++++++-- ...CollectionInitializerDiagnosticAnalyzer.cs | 11 +++++- ...UseCollectionInitializerCodeFixProvider.cs | 7 ++-- ...CollectionInitializerDiagnosticAnalyzer.vb | 4 +++ ...UseCollectionInitializerCodeFixProvider.vb | 3 +- 7 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs index 74f40ff39fe92..d5a41302a68f8 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs @@ -27,5 +27,10 @@ protected override bool AreCollectionInitializersSupported(Compilation compilati => compilation.LanguageVersion() >= LanguageVersion.CSharp3; protected override ISyntaxFacts GetSyntaxFacts() => CSharpSyntaxFacts.Instance; + + protected override bool PreferTrailingComma(SyntaxNodeAnalysisContext context) + { + return context.GetCSharpAnalyzerOptions().PreferTrailingComma.Value; + } } } diff --git a/src/Analyzers/CSharp/CodeFixes/UseCollectionInitializer/CSharpUseCollectionInitializerCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseCollectionInitializer/CSharpUseCollectionInitializerCodeFixProvider.cs index 931a70bb5063d..96f002a9c9f18 100644 --- a/src/Analyzers/CSharp/CodeFixes/UseCollectionInitializer/CSharpUseCollectionInitializerCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UseCollectionInitializer/CSharpUseCollectionInitializerCodeFixProvider.cs @@ -38,24 +38,27 @@ public CSharpUseCollectionInitializerCodeFixProvider() protected override StatementSyntax GetNewStatement( StatementSyntax statement, BaseObjectCreationExpressionSyntax objectCreation, - ImmutableArray matches) + ImmutableArray matches, + bool addTrailingComma) { return statement.ReplaceNode( objectCreation, - GetNewObjectCreation(objectCreation, matches)); + GetNewObjectCreation(objectCreation, matches, addTrailingComma)); } private static BaseObjectCreationExpressionSyntax GetNewObjectCreation( BaseObjectCreationExpressionSyntax objectCreation, - ImmutableArray matches) + ImmutableArray matches, + bool addTrailingComma) { return UseInitializerHelpers.GetNewObjectCreation( - objectCreation, CreateExpressions(objectCreation, matches)); + objectCreation, CreateExpressions(objectCreation, matches, addTrailingComma)); } private static SeparatedSyntaxList CreateExpressions( BaseObjectCreationExpressionSyntax objectCreation, - ImmutableArray matches) + ImmutableArray matches, + bool addTrailingComma) { using var _ = ArrayBuilder.GetInstance(out var nodesAndTokens); @@ -72,7 +75,7 @@ private static SeparatedSyntaxList CreateExpressions( .WithoutTrivia() .WithPrependedLeadingTrivia(newTrivia); - if (i < matches.Length - 1) + if (i < matches.Length - 1 || addTrailingComma) { nodesAndTokens.Add(newExpression); var commaToken = SyntaxFactory.Token(SyntaxKind.CommaToken) diff --git a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs index ffced1ca0a0f8..82768e9b9c29c 100644 --- a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.UseCollectionInitializer; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Test.Utilities; @@ -19,7 +20,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseCollectionInitialize public partial class UseCollectionInitializerTests { - private static async Task TestInRegularAndScriptAsync(string testCode, string fixedCode, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary) + private static async Task TestInRegularAndScriptAsync(string testCode, string fixedCode, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool preferTrailingComma = false) { await new VerifyCS.Test { @@ -27,7 +28,8 @@ private static async Task TestInRegularAndScriptAsync(string testCode, string fi TestCode = testCode, FixedCode = fixedCode, LanguageVersion = LanguageVersion.Preview, - TestState = { OutputKind = outputKind } + TestState = { OutputKind = outputKind }, + Options = { { CSharpCodeStyleOptions.PreferTrailingComma, preferTrailingComma } }, }.RunAsync(); } @@ -45,6 +47,34 @@ private static async Task TestMissingInRegularAndScriptAsync(string testCode, La await test.RunAsync(); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseCollectionInitializer)] + public async Task TestOnVariableDeclarator_PreferTrailingComma() + { + await TestInRegularAndScriptAsync( +@"using System.Collections.Generic; + +class C +{ + void M() + { + var c = [|new|] List(); + c.Add(1); + } +}", +@"using System.Collections.Generic; + +class C +{ + void M() + { + var c = new List + { + 1, + }; + } +}", true); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseCollectionInitializer)] public async Task TestOnVariableDeclarator() { diff --git a/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs index 99964ef9a0d60..daf3efca618b3 100644 --- a/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs @@ -31,6 +31,8 @@ internal abstract partial class AbstractUseCollectionInitializerDiagnosticAnalyz where TExpressionStatementSyntax : TStatementSyntax where TVariableDeclaratorSyntax : SyntaxNode { + internal const string PreferTrailingCommaKey = nameof(PreferTrailingCommaKey); + public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; @@ -45,6 +47,7 @@ protected AbstractUseCollectionInitializerDiagnosticAnalyzer() protected abstract ISyntaxFacts GetSyntaxFacts(); protected abstract bool AreCollectionInitializersSupported(Compilation compilation); + protected abstract bool PreferTrailingComma(SyntaxNodeAnalysisContext context); protected override void InitializeWorker(AnalysisContext context) => context.RegisterCompilationStartAction(OnCompilationStart); @@ -107,12 +110,18 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context, INamedTypeSymbol ien var locations = ImmutableArray.Create(objectCreationExpression.GetLocation()); + var properties = ImmutableDictionary.Empty; + if (PreferTrailingComma(context)) + { + properties = properties.Add(nameof(PreferTrailingCommaKey), ""); + } + context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, objectCreationExpression.GetFirstToken().GetLocation(), option.Notification.Severity, additionalLocations: locations, - properties: null)); + properties: properties)); FadeOutCode(context, matches.Value, locations); } diff --git a/src/Analyzers/Core/CodeFixes/UseCollectionInitializer/AbstractUseCollectionInitializerCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseCollectionInitializer/AbstractUseCollectionInitializerCodeFixProvider.cs index 172b901fe390d..d718e499030ff 100644 --- a/src/Analyzers/Core/CodeFixes/UseCollectionInitializer/AbstractUseCollectionInitializerCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/UseCollectionInitializer/AbstractUseCollectionInitializerCodeFixProvider.cs @@ -93,8 +93,8 @@ protected override async Task FixAllAsync( var statement = objectCreation.FirstAncestorOrSelf(); Contract.ThrowIfNull(statement); - - var newStatement = GetNewStatement(statement, objectCreation, matches.Value) + const string key = AbstractUseObjectInitializerDiagnosticAnalyzer.PreferTrailingCommaKey; + var newStatement = GetNewStatement(statement, objectCreation, matches.Value, addTrailingComma: diagnostics[0].Properties.ContainsKey(key)) .WithAdditionalAnnotations(Formatter.Annotation); var subEditor = new SyntaxEditor(currentRoot, services); @@ -113,6 +113,7 @@ protected override async Task FixAllAsync( protected abstract TStatementSyntax GetNewStatement( TStatementSyntax statement, TObjectCreationExpressionSyntax objectCreation, - ImmutableArray matches); + ImmutableArray matches, + bool addTrailingComma); } } diff --git a/src/Analyzers/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicUseCollectionInitializerDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicUseCollectionInitializerDiagnosticAnalyzer.vb index 65c1409ee484f..d899c500ca60b 100644 --- a/src/Analyzers/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicUseCollectionInitializerDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicUseCollectionInitializerDiagnosticAnalyzer.vb @@ -28,5 +28,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseCollectionInitializer Protected Overrides Function GetSyntaxFacts() As ISyntaxFacts Return VisualBasicSyntaxFacts.Instance End Function + + Protected Overrides Function PreferTrailingComma(context As SyntaxNodeAnalysisContext) As Boolean + Return False + End Function End Class End Namespace diff --git a/src/Analyzers/VisualBasic/CodeFixes/UseCollectionInitializer/VisualBasicUseCollectionInitializerCodeFixProvider.vb b/src/Analyzers/VisualBasic/CodeFixes/UseCollectionInitializer/VisualBasicUseCollectionInitializerCodeFixProvider.vb index 460742a47e92a..0d87827a3a17e 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/UseCollectionInitializer/VisualBasicUseCollectionInitializerCodeFixProvider.vb +++ b/src/Analyzers/VisualBasic/CodeFixes/UseCollectionInitializer/VisualBasicUseCollectionInitializerCodeFixProvider.vb @@ -31,7 +31,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseCollectionInitializer Protected Overrides Function GetNewStatement( statement As StatementSyntax, objectCreation As ObjectCreationExpressionSyntax, - matches As ImmutableArray(Of ExpressionStatementSyntax)) As StatementSyntax + matches As ImmutableArray(Of ExpressionStatementSyntax), + addTrailingComma As Boolean) As StatementSyntax Dim newStatement = statement.ReplaceNode( objectCreation, GetNewObjectCreation(objectCreation, matches)) From 9c9cb3f3f529cbde8d3d5d705e31ae1fc85c202a Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 25 Jun 2022 17:42:29 +0200 Subject: [PATCH 26/29] Few fixes --- .../AbstractUseCollectionInitializerCodeFixProvider.cs | 2 +- .../CSharpTest/Formatting/CodeCleanupTests.cs | 4 ++-- .../Test/CodeGeneration/CodeGenerationTests.CSharp.cs | 2 +- .../Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs | 6 ++++++ .../Core/Test/Options/CSharpEditorConfigGeneratorTests.vb | 2 ++ 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Analyzers/Core/CodeFixes/UseCollectionInitializer/AbstractUseCollectionInitializerCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseCollectionInitializer/AbstractUseCollectionInitializerCodeFixProvider.cs index d718e499030ff..df99e8f2c60c2 100644 --- a/src/Analyzers/Core/CodeFixes/UseCollectionInitializer/AbstractUseCollectionInitializerCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/UseCollectionInitializer/AbstractUseCollectionInitializerCodeFixProvider.cs @@ -93,7 +93,7 @@ protected override async Task FixAllAsync( var statement = objectCreation.FirstAncestorOrSelf(); Contract.ThrowIfNull(statement); - const string key = AbstractUseObjectInitializerDiagnosticAnalyzer.PreferTrailingCommaKey; + const string key = AbstractUseCollectionInitializerDiagnosticAnalyzer.PreferTrailingCommaKey; var newStatement = GetNewStatement(statement, objectCreation, matches.Value, addTrailingComma: diagnostics[0].Properties.ContainsKey(key)) .WithAdditionalAnnotations(Formatter.Annotation); diff --git a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs index b9a2c1a17f0e5..3057e1850b05d 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs @@ -579,8 +579,8 @@ public void VerifyAllCodeStyleFixersAreSupportedByCodeCleanup(string language) var expectedNumberOfUnsupportedDiagnosticIds = language switch { - LanguageNames.CSharp => 36, - LanguageNames.VisualBasic => 72, + LanguageNames.CSharp => 37, + LanguageNames.VisualBasic => 73CodeGenerationTests.CSharp, _ => throw ExceptionUtilities.UnexpectedValue(language), }; diff --git a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs index e7706f9195b6b..991596a1f87c2 100644 --- a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs +++ b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.CSharp.cs @@ -321,7 +321,7 @@ public async Task AddEnumWithValues() public enum E { F1 = 1, - F2 = 2 + F2 = 2, } }"; await TestAddNamedTypeAsync(input, expected, "E", diff --git a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs index e3d33475ee878..34bd63a8de723 100644 --- a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs +++ b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs @@ -393,6 +393,9 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() # IDE0083 dotnet_diagnostic.IDE0083.severity = %value% +# IDE0085 +dotnet_diagnostic.IDE0085.severity = %value% + # IDE0090 dotnet_diagnostic.IDE0090.severity = %value% @@ -1016,6 +1019,9 @@ No editorconfig based code style option # IDE0083, PreferNotPattern csharp_style_prefer_not_pattern = true +# IDE0085, PreferTrailingComma +csharp_style_prefer_trailing_comma = true + # IDE0090, ImplicitObjectCreationWhenTypeIsApparent csharp_style_implicit_object_creation_when_type_is_apparent = true diff --git a/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb b/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb index 3250dcaac36da..49f50df89a17f 100644 --- a/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb +++ b/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb @@ -140,6 +140,7 @@ csharp_style_prefer_index_operator = true csharp_style_prefer_local_over_anonymous_function = true csharp_style_prefer_null_check_over_type_check = true csharp_style_prefer_range_operator = true +csharp_style_prefer_trailing_comma = true csharp_style_prefer_tuple_swap = true csharp_style_prefer_utf8_string_literals = true csharp_style_throw_expression = true @@ -377,6 +378,7 @@ csharp_style_prefer_index_operator = true csharp_style_prefer_local_over_anonymous_function = true csharp_style_prefer_null_check_over_type_check = true csharp_style_prefer_range_operator = true +csharp_style_prefer_trailing_comma = true csharp_style_prefer_tuple_swap = true csharp_style_prefer_utf8_string_literals = true csharp_style_throw_expression = true From 7b7412e46173e673720bcf80a38e9cf338ffc08f Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sat, 25 Jun 2022 18:17:08 +0200 Subject: [PATCH 27/29] Fix build --- .../UseCollectionInitializer/UseCollectionInitializerTests.cs | 2 +- src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs index 82768e9b9c29c..1107c1f4b32e2 100644 --- a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs @@ -72,7 +72,7 @@ void M() 1, }; } -}", true); +}", preferTrailingComma: true); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseCollectionInitializer)] diff --git a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs index 3057e1850b05d..d6234ce98bc15 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs @@ -580,7 +580,7 @@ public void VerifyAllCodeStyleFixersAreSupportedByCodeCleanup(string language) language switch { LanguageNames.CSharp => 37, - LanguageNames.VisualBasic => 73CodeGenerationTests.CSharp, + LanguageNames.VisualBasic => 73, _ => throw ExceptionUtilities.UnexpectedValue(language), }; From 9f1680904ed1fb26d110febd683251bd2e22cfd6 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 8 Jul 2022 16:38:50 +0200 Subject: [PATCH 28/29] Fix formatting --- .../Tests/UseObjectInitializer/UseObjectInitializerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs index d2f3a02dde579..6e1c0cba48d6b 100644 --- a/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseObjectInitializer/UseObjectInitializerTests.cs @@ -27,7 +27,7 @@ private static async Task TestInRegularAndScriptAsync(string testCode, string fi FixedCode = fixedCode, LanguageVersion = LanguageVersion.Preview, TestState = { OutputKind = outputKind }, - Options = { { CSharpCodeStyleOptions.PreferTrailingComma, preferTrailingComma} } + Options = { { CSharpCodeStyleOptions.PreferTrailingComma, preferTrailingComma } } }.RunAsync(); } From 499ab631b1fa03651a06e725d2e7d686f422ee80 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 8 Jul 2022 17:21:32 +0200 Subject: [PATCH 29/29] Add test --- .../UseCollectionInitializerTests.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs index 1107c1f4b32e2..eea46b97a9097 100644 --- a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs +++ b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests.cs @@ -75,6 +75,45 @@ void M() }", preferTrailingComma: true); } + [Fact] + public async Task TestNestedCollectionInitializer_PreferTrailingComma() + { + await TestInRegularAndScriptAsync( +@"using System; +using System.Collections.Generic; + +class C +{ + void M() + { + var list1 = new List + { + () => + { + var list2 = [|new|] List(); + list2.Add(2); + } + }; + } +}", +@"using System; +using System.Collections.Generic; + +class C +{ + void M() + { + var list1 = new List + { + () => + { + var list2 = new List() { 2 }; + } + }; + } +}", preferTrailingComma: true); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseCollectionInitializer)] public async Task TestOnVariableDeclarator() {