-
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 analyzer/fixer to recommend updating stackalloc expressions to use collection expressions. #69414
Add analyzer/fixer to recommend updating stackalloc expressions to use collection expressions. #69414
Conversation
@@ -45,25 +45,23 @@ public CSharpUseCollectionExpressionForArrayDiagnosticAnalyzer() | |||
} | |||
|
|||
protected override void InitializeWorker(AnalysisContext context) | |||
=> context.RegisterCompilationStartAction(OnCompilationStart); |
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.
review with whitespace off.
this is just a method inline.
context.RegisterSyntaxNodeAction( | ||
context => AnalyzeMemberAccess(context), | ||
SyntaxKind.SimpleMemberAccessExpression); | ||
}); | ||
}); |
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 is just a method inline.
originalTypeInfo.ConvertedType.OriginalDefinition.Equals(compilation.ReadOnlySpanOfTType()); | ||
if (!isOk) | ||
return false; | ||
} |
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 code is saying: it's ok if using a collection expression would produce Span<T>
if the original code was ReadONlySpan<T>
. That's because the former is trivially implicitly convertible to the latter, despite being different types.
@@ -588,5 +588,36 @@ static IEnumerable<SyntaxNode> GetElementComponents(StatementSyntax statement) | |||
|
|||
static StatementSyntax UnwrapEmbeddedStatement(StatementSyntax statement) | |||
=> statement is BlockSyntax { Statements: [var innerStatement] } ? innerStatement : statement; | |||
|
|||
static ExpressionSyntax ConvertExpression( |
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 moved from common code to be specific to collection-expressions and specific to colleciton-initializers. it turned out sharing just was not possible. Especially because if you had x[a] = b
then collection expressions would add this as just b
whereas collection initializers would add it as [a] = b
.
Given that, it would be too many contortions to try to share. so i just pulled out for eahc.
@@ -39,7 +39,7 @@ protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic) | |||
|
|||
public override Task RegisterCodeFixesAsync(CodeFixContext context) | |||
{ | |||
RegisterCodeFix(context, CSharpCodeFixesResources.Use_collection_expression, nameof(CSharpCodeFixesResources.Use_collection_expression)); | |||
RegisterCodeFix(context, CSharpCodeFixesResources.Use_collection_expression, IDEDiagnosticIds.UseCollectionExpressionForEmptyDiagnosticId); |
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.
we want different equivalence keys so that we don't wrong the wrong fixers on the wrong diagnostics.
@@ -2123,7 +2123,7 @@ public class Goo | |||
public void M() | |||
{ | |||
int lastItem; | |||
List<int> list = [(lastItem = 5)]; | |||
List<int> list = [lastItem = 5]; |
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 is an improvement. the latter is legal in a collection expression (but was not legal in a collection initializer). No longer sharing code between the two improved this.
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); | ||
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); | ||
var currentRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); | ||
var semanticDocument = await SemanticDocument.CreateAsync( |
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.
swithcing to SemanticDOcument moved us from 4 local variables to 1.
semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); | ||
currentRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); | ||
semanticDocument = await semanticDocument.WithSyntaxRootAsync( | ||
subEditor.GetChangedRoot(), cancellationToken).ConfigureAwait(false); |
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.
only one variable to update versus 4.
Part of #69132.
Followup to #69407. That should be reviewed and go in first.
Supports cases like:
Also supports;