diff --git a/ChangeLog.md b/ChangeLog.md index dc790f4111..3522b637fc 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Rename analyzers ([PR](https://github.com/dotnet/roslynator/pull/1314)) - "Add new line before embedded statement" -> "Put embedded statement on its own line" ([RCS0030](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0030)) - "Add new line before statement" -> "Put statement on its own line" ([RCS0033](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS0033)) +- Group refactoring "Wrap in ..." ([PR](https://github.com/dotnet/roslynator/pull/1317)) ### Fixed diff --git a/src/Refactorings/CSharp/Refactorings/EmbeddedStatementRefactoring.cs b/src/Refactorings/CSharp/Refactorings/EmbeddedStatementRefactoring.cs index dc0f24dc6a..94cf81581b 100644 --- a/src/Refactorings/CSharp/Refactorings/EmbeddedStatementRefactoring.cs +++ b/src/Refactorings/CSharp/Refactorings/EmbeddedStatementRefactoring.cs @@ -14,7 +14,7 @@ public static void ComputeRefactoring(RefactoringContext context, StatementSynta if (context.IsRefactoringEnabled(RefactoringDescriptors.WrapStatementsInCondition)) { - context.RegisterRefactoring( + context.AddNestedCodeAction( WrapInIfStatementRefactoring.Title, ct => WrapInIfStatementRefactoring.Instance.RefactorAsync(context.Document, statement, ct), RefactoringDescriptors.WrapStatementsInCondition); @@ -22,7 +22,7 @@ public static void ComputeRefactoring(RefactoringContext context, StatementSynta if (context.IsRefactoringEnabled(RefactoringDescriptors.WrapLinesInTryCatch)) { - context.RegisterRefactoring( + context.AddNestedCodeAction( WrapLinesInTryCatchRefactoring.Title, ct => WrapLinesInTryCatchRefactoring.Instance.RefactorAsync(context.Document, statement, ct), RefactoringDescriptors.WrapLinesInTryCatch); diff --git a/src/Refactorings/CSharp/Refactorings/RefactoringContext.cs b/src/Refactorings/CSharp/Refactorings/RefactoringContext.cs index dc8d9efb3d..adae427ddc 100644 --- a/src/Refactorings/CSharp/Refactorings/RefactoringContext.cs +++ b/src/Refactorings/CSharp/Refactorings/RefactoringContext.cs @@ -38,6 +38,8 @@ public RefactoringContext(CodeRefactoringContext underlyingContext, SyntaxNode r public SyntaxNode Root { get; } + public ImmutableArray.Builder NestedCodeActions { get; private set; } + public CancellationToken CancellationToken { get { return UnderlyingContext.CancellationToken; } @@ -77,50 +79,33 @@ public bool SupportsCSharp6 { get { - if (Project.Language == LanguageNames.CSharp) - { - switch (((CSharpParseOptions)Project.ParseOptions).LanguageVersion) - { - case LanguageVersion.CSharp1: - case LanguageVersion.CSharp2: - case LanguageVersion.CSharp3: - case LanguageVersion.CSharp4: - case LanguageVersion.CSharp5: - return false; - default: - return true; - } - } - - return false; + return Project.Language == LanguageNames.CSharp + && ((CSharpParseOptions)Project.ParseOptions).LanguageVersion >= LanguageVersion.CSharp6; } } - public bool SupportsCSharp7 + public bool PrefixFieldIdentifierWithUnderscore => (_configOptions ??= Document.GetConfigOptions(Root.SyntaxTree)).GetPrefixFieldIdentifierWithUnderscore(); + + public void AddNestedCodeAction( + string title, + Func> createChangedDocument, + RefactoringDescriptor descriptor, + string additionalEquivalenceKey1 = null, + string additionalEquivalenceKey2 = null) { - get - { - if (Project.Language == LanguageNames.CSharp) - { - switch (((CSharpParseOptions)Project.ParseOptions).LanguageVersion) - { - case LanguageVersion.CSharp1: - case LanguageVersion.CSharp2: - case LanguageVersion.CSharp3: - case LanguageVersion.CSharp4: - case LanguageVersion.CSharp5: - case LanguageVersion.CSharp6: - return false; - default: - return true; - } - } + NestedCodeActions ??= ImmutableArray.CreateBuilder(); - return false; - } + NestedCodeActions.Add(CodeAction.Create( + title, + createChangedDocument, + EquivalenceKey.Create(descriptor, additionalEquivalenceKey1, additionalEquivalenceKey2))); } - public bool PrefixFieldIdentifierWithUnderscore => (_configOptions ??= Document.GetConfigOptions(Root.SyntaxTree)).GetPrefixFieldIdentifierWithUnderscore(); + public void RegisterNestedCodeActions(string title) + { + if (NestedCodeActions is not null) + UnderlyingContext.RegisterRefactoring(CodeAction.Create(title, NestedCodeActions.ToImmutable(), isInlinable: false)); + } public void ThrowIfCancellationRequested() { diff --git a/src/Refactorings/CSharp/Refactorings/SelectedLinesRefactoring.cs b/src/Refactorings/CSharp/Refactorings/SelectedLinesRefactoring.cs index dba22734d9..2c80ad9d35 100644 --- a/src/Refactorings/CSharp/Refactorings/SelectedLinesRefactoring.cs +++ b/src/Refactorings/CSharp/Refactorings/SelectedLinesRefactoring.cs @@ -54,19 +54,21 @@ public static async Task ComputeRefactoringsAsync(RefactoringContext context, Sy { if (context.IsRefactoringEnabled(RefactoringDescriptors.WrapLinesInRegion)) { - context.RegisterRefactoring( - "Wrap in #region", + context.AddNestedCodeAction( + "#region", ct => WrapLinesInRegionRefactoring.Instance.RefactorAsync(document, selectedLines, ct), RefactoringDescriptors.WrapLinesInRegion); } if (context.IsRefactoringEnabled(RefactoringDescriptors.WrapLinesInPreprocessorDirective)) { - context.RegisterRefactoring( - "Wrap in #if", + context.AddNestedCodeAction( + "#if", ct => WrapLinesInPreprocessorDirectiveRefactoring.Instance.RefactorAsync(document, selectedLines, ct), RefactoringDescriptors.WrapLinesInPreprocessorDirective); } + + context.RegisterNestedCodeActions("Wrap in"); } if (context.IsRefactoringEnabled(RefactoringDescriptors.RemoveEmptyLines)) diff --git a/src/Refactorings/CSharp/Refactorings/SelectedStatementsRefactoring.cs b/src/Refactorings/CSharp/Refactorings/SelectedStatementsRefactoring.cs index faa912b689..e0287af14d 100644 --- a/src/Refactorings/CSharp/Refactorings/SelectedStatementsRefactoring.cs +++ b/src/Refactorings/CSharp/Refactorings/SelectedStatementsRefactoring.cs @@ -79,7 +79,7 @@ public static async Task ComputeRefactoringAsync(RefactoringContext context, Sta if (context.IsRefactoringEnabled(RefactoringDescriptors.WrapStatementsInCondition)) { - context.RegisterRefactoring( + context.AddNestedCodeAction( WrapInIfStatementRefactoring.Title, ct => WrapInIfStatementRefactoring.Instance.RefactorAsync(context.Document, selectedStatements, ct), RefactoringDescriptors.WrapStatementsInCondition); @@ -87,7 +87,7 @@ public static async Task ComputeRefactoringAsync(RefactoringContext context, Sta if (context.IsRefactoringEnabled(RefactoringDescriptors.WrapLinesInTryCatch)) { - context.RegisterRefactoring( + context.AddNestedCodeAction( WrapLinesInTryCatchRefactoring.Title, ct => WrapLinesInTryCatchRefactoring.Instance.RefactorAsync(context.Document, selectedStatements, ct), RefactoringDescriptors.WrapLinesInTryCatch); diff --git a/src/Refactorings/CSharp/Refactorings/WrapStatements/WrapInIfStatementRefactoring.cs b/src/Refactorings/CSharp/Refactorings/WrapStatements/WrapInIfStatementRefactoring.cs index 66349b8ca1..2d890d0f7b 100644 --- a/src/Refactorings/CSharp/Refactorings/WrapStatements/WrapInIfStatementRefactoring.cs +++ b/src/Refactorings/CSharp/Refactorings/WrapStatements/WrapInIfStatementRefactoring.cs @@ -16,7 +16,7 @@ private WrapInIfStatementRefactoring() public static WrapInIfStatementRefactoring Instance { get; } = new(); - public const string Title = "Wrap in condition"; + public const string Title = "'if' statement"; public override IfStatementSyntax CreateStatement(ImmutableArray statements) { diff --git a/src/Refactorings/CSharp/Refactorings/WrapStatements/WrapLinesInTryCatchRefactoring.cs b/src/Refactorings/CSharp/Refactorings/WrapStatements/WrapLinesInTryCatchRefactoring.cs index 8772b59d9a..9ab76d2078 100644 --- a/src/Refactorings/CSharp/Refactorings/WrapStatements/WrapLinesInTryCatchRefactoring.cs +++ b/src/Refactorings/CSharp/Refactorings/WrapStatements/WrapLinesInTryCatchRefactoring.cs @@ -9,7 +9,7 @@ namespace Roslynator.CSharp.Refactorings.WrapStatements; internal sealed class WrapLinesInTryCatchRefactoring : WrapStatementsRefactoring { - public const string Title = "Wrap in try-catch"; + public const string Title = "try-catch"; private WrapLinesInTryCatchRefactoring() {