-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Add support for converting existing collection-initializers over to collection expressions. #69321
Add support for converting existing collection-initializers over to collection expressions. #69321
Conversation
@@ -169,4 +176,101 @@ bool IsInTargetTypedBinaryExpression(BinaryExpressionSyntax binaryExpression, Ex | |||
return binaryExpression.Kind() == SyntaxKind.CoalesceExpression && binaryExpression.Right == expression && HasType(binaryExpression.Left); | |||
} | |||
} | |||
|
|||
public static CollectionExpressionSyntax ConvertInitializerToCollectionExpression( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this helper is used by multiple fixers. SO it moved to this common location.
SourceText sourceText, | ||
InitializerExpressionSyntax originalInitializer, | ||
CollectionExpressionSyntax newCollectionExpression, | ||
bool newCollectionIsSingleLine) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same with this helper.
@@ -83,59 +85,9 @@ void RewriteInitializerExpression(InitializerExpressionSyntax initializer) | |||
IsOnSingleLine(sourceText, initializer))); | |||
} | |||
|
|||
bool ShouldReplaceExistingExpressionEntirely(ExpressionSyntax explicitOrImplicitArray, InitializerExpressionSyntax initializer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this helper moved to a common location.
|
||
private static CollectionExpressionSyntax ConvertInitializerToCollectionExpression( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this helper moved to a common location.
@@ -25,7 +23,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseCollectionInitializer | |||
using static SyntaxFactory; | |||
|
|||
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.UseCollectionInitializer), Shared] | |||
internal class CSharpUseCollectionInitializerCodeFixProvider : | |||
internal partial class CSharpUseCollectionInitializerCodeFixProvider : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this type changed a ton. It is now 3 files. The main one, with common logic. And then two siblings. One sibling is for creating object-initializers, the other for object-creation expressions.
ImmutableArray<Match<StatementSyntax>> matches) | ||
{ | ||
var expressions = CreateCollectionInitializerExpressions(); | ||
var withLineBreaks = AddLineBreaks(expressions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the collection initializer case is pretty simple. We create a list of all the expressions, then add lines breaks between the elements (we always do initializers across multiple lines).
Note: in the future we may want to copy the code that properly indents expressions so that when we move expressions into the collection initializer we do a good job with multi-line exprs.
List<int> c = | ||
[ | ||
1, 2 | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lots of tests got better now that we rewrote the formatting logic for collection-exprs.
2, | ||
]; | ||
} | ||
} | ||
"""); | ||
} | ||
|
||
[Fact] | ||
public async Task TestReplacementLocation_NoElements_ExistingInitializer1() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thus begins a huge swath of tests created to validate a ton of whitespace/newline trivia scenarios.
/// Creates the final collection-expression <c>[...]</c> that will replace the given <paramref | ||
/// name="objectCreation"/> expression. | ||
/// </summary> | ||
private static async Task<CollectionExpressionSyntax> CreateCollectionExpressionAsync( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this logic is effectively entirely new. The code heavily emphasizes trying to match the new collection-expression style against the current code the user has (or infer what would be best for certain situations). I've tried to doc it heavily as to what it's doing.
@@ -218,28 +231,13 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context, INamedTypeSymbol ien | |||
|
|||
return (matches, shouldUseCollectionExpression: true); | |||
} | |||
|
|||
bool AreCollectionExpressionsSupported() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just inlined this method.
...s/VisualBasic/Analyzers/UseCollectionInitializer/VisualBasicCollectionInitializerAnalyzer.vb
Show resolved
Hide resolved
…isualBasicCollectionInitializerAnalyzer.vb
@akhera99 This is ready for review. THe tests should hopefully help indicate what's going on here and why so much was rewritten :) |
List<int> c = [|new|] List<int>(); | ||
// Goo | ||
// Bar | ||
if (b1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a test like so
if (b1) | |
if (b1) // Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. i'll add in followup pr. right now that comment will be removed.
Part of #69132
Draft until #69280 goes in.
This means code like
new List<int> { 1, 2, 3 }
will get converted to[1, 2, 3]
. We also detect this in the long-statement form like:And offer a similar conversion. Additionally we support converting things like:
to:
[1, 2, .. v]
, and so on.Note: this also works when the initializer already exists. For example:
We try very hard to produce a collection expression that matches the style present, or looks good when no style is present. This involved effectively rewriting the entire core logic taht generates collection expressions to not use the formatting engine at all, but instead manually create everything from scratch. This adds a lot of logic, but makes the end results much higher quality.