-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Implement Initializer expression wrappers #39878
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
CyrusNajmabadi
merged 58 commits into
dotnet:main
from
tokarzkj:initializer-expression-wrapper
Feb 11, 2022
Merged
Changes from all commits
Commits
Show all changes
58 commits
Select commit
Hold shift + click to select a range
4e4da79
Add initial unit tests for initializer expression wrapping
tokarzkj 18e990b
Setup collection expression wrapper for visual basic
tokarzkj fc3fbf5
Add featured resources for refactorings
tokarzkj 8ade65d
Add the unwrap all refactoring option
tokarzkj 05d4b92
Add the refactor long initializer line option
tokarzkj ca2ec2d
Get the vb implementation of the refactorings working
tokarzkj 19f2900
Implement a method to get the spacing for the closing brace
tokarzkj 84fa036
Implement the initializer expression wrapper for csharp
tokarzkj 25665d9
Get the initializer refactoring working for c#
tokarzkj 928bcec
Fix the code refactorings for the initializer expression wrapper
tokarzkj 435202d
Fix the long initializer test case that was failing
tokarzkj 4783120
Get the final TestWrappingShortInitializerTest to work
tokarzkj 542e210
Add additional tests to confirm the other refactorings are offered
tokarzkj 95d9314
Add Visual Basic tests to confirm the initializer expression wrapper …
tokarzkj bed95c2
Rename variables that broke up naming conventions
tokarzkj 3eb818e
Merge branch 'master' into initializer-expression-wrapper
tokarzkj 9ea3cfa
Merge in the latest FeatureResources.resx changes
tokarzkj 1db82d3
Add copy right to new files
tokarzkj fa5f597
Add missing FeatureResources for the refactoring labels
tokarzkj 6dcc926
Remove the PositionIsApplicable method
tokarzkj 9e372f4
Add a unit test confirming long initializers wraps multiple lines
tokarzkj 5d83935
Add a DeclarationKind that maps to the return syntax kinds
tokarzkj 0ab2674
Revert "Add a DeclarationKind that maps to the return syntax kinds"
tokarzkj 5ecb111
Remove GetNestedCodeActionTitle since there is only one choice
tokarzkj cb5cd75
Use the indentation service to place the open brace
tokarzkj f99b5c9
Merge branch 'master' into initializer-expression-wrapper
tokarzkj b739b69
Merge branch 'master' into initializer-expression-wrapper
tokarzkj 65af13a
Remove the language specific abstract initializer expression wrappers
tokarzkj d7278b4
Use the csharp option for determing if the open brace should be on a …
tokarzkj 35f4fe3
Refactor the common logic between initializerexpressionwrapper and se…
tokarzkj ff2a563
Adjust accessiblity modifiers for some methods in AbstractSeparatedLi…
tokarzkj 5b980af
Add missing copyright notices in new files
tokarzkj 57c3577
Enable nullable references in the SeparatedListWrapper
tokarzkj 5109b8f
Merge branch 'master' into initializer-expression-wrapper
tokarzkj f576ade
Seal overrides in the SeparatedList classes to prevent further extending
tokarzkj 174dfd8
Switch virtual classes to be abstract in SeparatedList
tokarzkj 2b64c2c
Add a comment for determining the opening brace position in VB
tokarzkj b9cb00b
Fix labeling of refactoring options for initializers
tokarzkj e369959
Move the WrappingStyle to Label mapping into a function
tokarzkj bc875e8
Add a comment explaining unique SeparatedSyntaxList refactorings
tokarzkj 3c05f67
Switch to block indentation for the brace indentation
tokarzkj 9dd1287
Switch one line functions to expression bodied members
tokarzkj bffd11a
Add additional tests for return statements
tokarzkj 622cc78
Add unit tests for initializers in class properties
tokarzkj c9900c4
Add unit tests for using initializers passed to functions
tokarzkj bce94aa
Update src/Features/Core/Portable/Wrapping/AbstractSeparatedListCodeC…
tokarzkj 2aecfef
Switch the remaining virtual methods to abstract in AbstractSeparated…
tokarzkj 551d7c9
Check if the syntaxroot is null
tokarzkj d8ede78
Merge branch 'initializer-expression-wrapper' of https://github.com/t…
tokarzkj 440495c
Update src/Features/Core/Portable/Wrapping/AbstractSeparatedListCodeC…
tokarzkj 98626eb
Apply remove configure await suggestions from code review
tokarzkj 4cfc5d2
Apply additional remove async suggestions from code review
tokarzkj 7b4d3da
Merge remote-tracking branch 'dotnet/main' into initializer-expressio…
sharwell 0df701b
Inline helper method GetSmartIndentationAfter
sharwell 425c27b
Rename new files to match type names
sharwell 6d89888
Merge remote-tracking branch 'upstream/main' into initializer-express…
CyrusNajmabadi 4bea76b
Update coyright
CyrusNajmabadi 8ac5632
Merge remote-tracking branch 'upstream/main' into initializer-express…
CyrusNajmabadi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
535 changes: 535 additions & 0 deletions
535
src/EditorFeatures/CSharpTest/Wrapping/InitializerExpressionWrappingTests.cs
Large diffs are not rendered by default.
Oops, something went wrong.
431 changes: 431 additions & 0 deletions
431
src/EditorFeatures/VisualBasicTest/Wrapping/InitializerExpressionWrappingTests.vb
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
...ures/CSharp/Portable/Wrapping/InitializerExpression/CSharpInitializerExpressionWrapper.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// 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 Microsoft.CodeAnalysis.CSharp.Formatting; | ||
using Microsoft.CodeAnalysis.CSharp.Indentation; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Options; | ||
using Microsoft.CodeAnalysis.Wrapping.InitializerExpression; | ||
|
||
namespace Microsoft.CodeAnalysis.CSharp.Wrapping.InitializerExpression | ||
{ | ||
internal partial class CSharpInitializerExpressionWrapper : AbstractInitializerExpressionWrapper<InitializerExpressionSyntax, ExpressionSyntax> | ||
{ | ||
public CSharpInitializerExpressionWrapper() : base(CSharpIndentationService.Instance) | ||
{ | ||
} | ||
|
||
protected override SeparatedSyntaxList<ExpressionSyntax> GetListItems(InitializerExpressionSyntax listSyntax) | ||
=> listSyntax.Expressions; | ||
|
||
protected override InitializerExpressionSyntax? TryGetApplicableList(SyntaxNode node) | ||
=> node as InitializerExpressionSyntax; | ||
|
||
protected override bool TryGetNewLinesForBracesInObjectCollectionArrayInitializersOption(DocumentOptionSet options) | ||
=> options.GetOption(CSharpFormattingOptions.NewLinesForBracesInObjectCollectionArrayInitializers); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
176 changes: 176 additions & 0 deletions
176
...e/Portable/Wrapping/AbstractSeparatedListWrapper`2+AbstractSeparatedListCodeComputer`1.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// 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.Collections.Immutable; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis.Editing; | ||
using Microsoft.CodeAnalysis.Formatting; | ||
using Microsoft.CodeAnalysis.Options; | ||
using Microsoft.CodeAnalysis.PooledObjects; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
using Microsoft.CodeAnalysis.Text; | ||
using Microsoft.CodeAnalysis.Wrapping.SeparatedSyntaxList; | ||
using Roslyn.Utilities; | ||
|
||
namespace Microsoft.CodeAnalysis.Wrapping | ||
{ | ||
internal abstract partial class AbstractSeparatedListWrapper<TListSyntax, TListItemSyntax> | ||
{ | ||
protected abstract class AbstractSeparatedListCodeComputer<TWrapper> : AbstractCodeActionComputer<TWrapper> | ||
CyrusNajmabadi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
where TWrapper : AbstractSeparatedListWrapper<TListSyntax, TListItemSyntax> | ||
{ | ||
protected readonly TListSyntax _listSyntax; | ||
protected readonly SeparatedSyntaxList<TListItemSyntax> _listItems; | ||
|
||
/// <summary> | ||
/// The indentation string necessary to indent an item in a list such that the start of | ||
/// that item will exact start at the end of the open-token for the containing list. i.e. | ||
/// | ||
/// void Goobar( | ||
/// ^ | ||
/// | | ||
/// | ||
/// This is the indentation we want when we're aligning wrapped items with the first item | ||
/// in the list. | ||
/// </summary> | ||
protected readonly SyntaxTrivia _afterOpenTokenIndentationTrivia; | ||
|
||
/// <summary> | ||
/// Indentation amount for any items that have been wrapped to a new line. Valid if we're | ||
/// not aligning with the first item. i.e. | ||
/// | ||
/// void Goobar( | ||
/// ^ | ||
/// | | ||
/// </summary> | ||
protected readonly SyntaxTrivia _singleIndentationTrivia; | ||
|
||
public AbstractSeparatedListCodeComputer( | ||
TWrapper service, | ||
Document document, SourceText sourceText, DocumentOptionSet options, | ||
TListSyntax listSyntax, SeparatedSyntaxList<TListItemSyntax> listItems, | ||
CancellationToken cancellationToken) | ||
: base(service, document, sourceText, options, cancellationToken) | ||
{ | ||
_listSyntax = listSyntax; | ||
_listItems = listItems; | ||
|
||
var generator = SyntaxGenerator.GetGenerator(OriginalDocument); | ||
|
||
_afterOpenTokenIndentationTrivia = generator.Whitespace(GetAfterOpenTokenIdentation()); | ||
_singleIndentationTrivia = generator.Whitespace(GetSingleIdentation()); | ||
} | ||
|
||
private string GetAfterOpenTokenIdentation() | ||
{ | ||
var openToken = _listSyntax.GetFirstToken(); | ||
var afterOpenTokenOffset = OriginalSourceText.GetOffset(openToken.Span.End); | ||
|
||
var indentString = afterOpenTokenOffset.CreateIndentationString(UseTabs, TabSize); | ||
return indentString; | ||
} | ||
|
||
private string GetSingleIdentation() | ||
{ | ||
// Insert a newline after the open token of the list. Then ask the | ||
// ISynchronousIndentationService where it thinks that the next line should be | ||
// indented. | ||
var openToken = _listSyntax.GetFirstToken(); | ||
|
||
return GetIndentationAfter(openToken, FormattingOptions.IndentStyle.Smart); | ||
} | ||
|
||
protected void AddTextChangeBetweenOpenAndFirstItem( | ||
WrappingStyle wrappingStyle, ArrayBuilder<Edit> result) | ||
{ | ||
result.Add(wrappingStyle == WrappingStyle.WrapFirst_IndentRest | ||
? Edit.UpdateBetween(_listSyntax.GetFirstToken(), NewLineTrivia, _singleIndentationTrivia, _listItems[0]) | ||
: Edit.DeleteBetween(_listSyntax.GetFirstToken(), _listItems[0])); | ||
} | ||
|
||
protected abstract string GetNestedCodeActionTitle(WrappingStyle wrappingStyle); | ||
|
||
protected async Task AddWrappingGroupsAsync(ArrayBuilder<WrappingGroup> result) | ||
{ | ||
result.Add(await GetWrapEveryGroupAsync().ConfigureAwait(false)); | ||
result.Add(await GetUnwrapGroupAsync().ConfigureAwait(false)); | ||
result.Add(await GetWrapLongGroupAsync().ConfigureAwait(false)); | ||
} | ||
|
||
#region unwrap group | ||
|
||
protected abstract Task<WrappingGroup> GetUnwrapGroupAsync(); | ||
|
||
protected abstract Task<WrapItemsAction> GetUnwrapAllCodeActionAsync(string parentTitle, WrappingStyle wrappingStyle); | ||
|
||
protected abstract ImmutableArray<Edit> GetUnwrapAllEdits(WrappingStyle wrappingStyle); | ||
|
||
// This computes edits for the content of the list excluding the opening token | ||
protected ImmutableArray<Edit> GetSeparatedListEdits(WrappingStyle wrappingStyle) | ||
{ | ||
using var _ = ArrayBuilder<Edit>.GetInstance(out var result); | ||
|
||
AddTextChangeBetweenOpenAndFirstItem(wrappingStyle, result); | ||
|
||
foreach (var comma in _listItems.GetSeparators()) | ||
{ | ||
result.Add(Edit.DeleteBetween(comma.GetPreviousToken(), comma)); | ||
result.Add(Edit.DeleteBetween(comma, comma.GetNextToken())); | ||
} | ||
|
||
result.Add(Edit.DeleteBetween(_listItems.Last(), _listSyntax.GetLastToken())); | ||
return result.ToImmutableAndClear(); | ||
} | ||
|
||
#endregion | ||
|
||
#region wrap long line | ||
|
||
protected abstract Task<WrappingGroup> GetWrapLongGroupAsync(); | ||
|
||
protected Task<WrapItemsAction> GetWrapLongLineCodeActionAsync( | ||
string parentTitle, WrappingStyle wrappingStyle) | ||
{ | ||
var indentationTrivia = GetIndentationTrivia(wrappingStyle); | ||
|
||
var edits = GetWrapLongLinesEdits(wrappingStyle, indentationTrivia); | ||
var title = GetNestedCodeActionTitle(wrappingStyle); | ||
|
||
return TryCreateCodeActionAsync(edits, parentTitle, title); | ||
} | ||
|
||
protected abstract ImmutableArray<Edit> GetWrapLongLinesEdits( | ||
WrappingStyle wrappingStyle, SyntaxTrivia indentationTrivia); | ||
|
||
#endregion | ||
|
||
#region Wrap every | ||
|
||
protected abstract Task<WrappingGroup> GetWrapEveryGroupAsync(); | ||
|
||
protected Task<WrapItemsAction> GetWrapEveryNestedCodeActionAsync( | ||
string parentTitle, WrappingStyle wrappingStyle) | ||
{ | ||
var indentationTrivia = GetIndentationTrivia(wrappingStyle); | ||
|
||
var edits = GetWrapEachEdits(wrappingStyle, indentationTrivia); | ||
var title = GetNestedCodeActionTitle(wrappingStyle); | ||
|
||
return TryCreateCodeActionAsync(edits, parentTitle, title); | ||
} | ||
|
||
protected abstract ImmutableArray<Edit> GetWrapEachEdits(WrappingStyle wrappingStyle, SyntaxTrivia indentationTrivia); | ||
|
||
private SyntaxTrivia GetIndentationTrivia(WrappingStyle wrappingStyle) | ||
{ | ||
return wrappingStyle == WrappingStyle.UnwrapFirst_AlignRest | ||
? _afterOpenTokenIndentationTrivia | ||
: _singleIndentationTrivia; | ||
} | ||
|
||
#endregion | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/Features/Core/Portable/Wrapping/AbstractSeparatedListWrapper`2.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// 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 Microsoft.CodeAnalysis.Indentation; | ||
|
||
namespace Microsoft.CodeAnalysis.Wrapping | ||
{ | ||
/// <summary> | ||
/// Base type for all wrappers that involve wrapping a comma-separated list of items. | ||
/// </summary> | ||
internal abstract partial class AbstractSeparatedListWrapper< | ||
TListSyntax, | ||
TListItemSyntax> | ||
: AbstractSyntaxWrapper | ||
where TListSyntax : SyntaxNode | ||
where TListItemSyntax : SyntaxNode | ||
{ | ||
protected abstract string Unwrap_list { get; } | ||
protected abstract string Wrap_long_list { get; } | ||
protected abstract string Unwrap_all_items { get; } | ||
protected abstract string Indent_all_items { get; } | ||
protected abstract string Wrap_every_item { get; } | ||
|
||
public AbstractSeparatedListWrapper(IIndentationService indentationService) | ||
: base(indentationService) | ||
{ | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.