/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Analyzers/CSharp/CodeFixes/UseCollectionInitializer/CSharpUseCollectionInitializerCodeFixProvider_CollectionInitializer.cs
143 строки
6 KB
Cyrus Najmabadi
Remove unnecessary imports
10 мар 2025, 17:04
10 мар 2025, 17:04
58c992f
Код
Авторство
О чём код?
// 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.Linq; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.UseObjectInitializer; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.UseCollectionExpression; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.UseCollectionInitializer; using static CSharpSyntaxTokens; using static SyntaxFactory; internal sealed partial class CSharpUseCollectionInitializerCodeFixProvider { private static BaseObjectCreationExpressionSyntax CreateObjectInitializerExpression( BaseObjectCreationExpressionSyntax objectCreation, ImmutableArray<CollectionMatch<SyntaxNode>> matches) { var expressions = CreateCollectionInitializerExpressions(); var withLineBreaks = AddLineBreaks(expressions); var newCreation = UseInitializerHelpers.GetNewObjectCreation(objectCreation, withLineBreaks); return newCreation.WithAdditionalAnnotations(Formatter.Annotation); SeparatedSyntaxList<ExpressionSyntax> CreateCollectionInitializerExpressions() { using var _ = ArrayBuilder<SyntaxNodeOrToken>.GetInstance(out var nodesAndTokens); UseInitializerHelpers.AddExistingItems<CollectionMatch<SyntaxNode>, ExpressionSyntax>( objectCreation, nodesAndTokens, addTrailingComma: matches.Length > 0, static (_, expression) => expression); for (var i = 0; i < matches.Length; i++) { var match = matches[i]; var statement = (ExpressionStatementSyntax)match.Node; var trivia = statement.GetLeadingTrivia(); var leadingTrivia = i == 0 ? trivia.WithoutLeadingBlankLines() : trivia; var trailingTrivia = statement.SemicolonToken.TrailingTrivia.Contains(static t => t.IsSingleOrMultiLineComment()) ? statement.SemicolonToken.TrailingTrivia : default; var expression = ConvertExpression(statement.Expression) .WithTrailingTrivia() .WithLeadingTrivia(leadingTrivia); if (i < matches.Length - 1) { nodesAndTokens.Add(expression); nodesAndTokens.Add(CommaToken.WithTrailingTrivia(trailingTrivia)); } else { nodesAndTokens.Add(expression.WithTrailingTrivia(trailingTrivia)); } } return SeparatedList<ExpressionSyntax>(nodesAndTokens); } static SeparatedSyntaxList<TNode> AddLineBreaks<TNode>(SeparatedSyntaxList<TNode> nodes) where TNode : SyntaxNode { using var _ = ArrayBuilder<SyntaxNodeOrToken>.GetInstance(out var nodesAndTokens); var nodeOrTokenList = nodes.GetWithSeparators(); foreach (var item in nodeOrTokenList) { var addLineBreak = item.IsToken || item == nodeOrTokenList.Last(); if (addLineBreak && item.GetTrailingTrivia() is not [.., (kind: SyntaxKind.EndOfLineTrivia)]) { nodesAndTokens.Add(item.WithAppendedTrailingTrivia(ElasticCarriageReturnLineFeed)); } else { nodesAndTokens.Add(item); } } return SeparatedList<TNode>(nodesAndTokens); } static ExpressionSyntax ConvertExpression( ExpressionSyntax expression) { // This must be called from an expression from the original tree. Not something we're already transforming. // Otherwise, we'll have no idea how to apply the preferredIndentation if present. Contract.ThrowIfNull(expression.Parent); return expression switch { InvocationExpressionSyntax invocation => ConvertInvocation(invocation), AssignmentExpressionSyntax assignment => ConvertAssignment(assignment), _ => throw new InvalidOperationException(), }; } static AssignmentExpressionSyntax ConvertAssignment(AssignmentExpressionSyntax assignment) { var elementAccess = (ElementAccessExpressionSyntax)assignment.Left; return assignment.WithLeft( ImplicitElementAccess(elementAccess.ArgumentList)); } static ExpressionSyntax ConvertInvocation(InvocationExpressionSyntax invocation) { var arguments = invocation.ArgumentList.Arguments; if (arguments.Count == 1) { // Assignment expressions in a collection initializer will cause the compiler to report an error. // This is because { a = b } is the form for an object initializer, and the two forms are not // allowed to mix/match. Parenthesize the assignment to avoid the ambiguity. // // Similarly, we cannot have `{ [...] }` in an object initializer (because it will be viewed as a // dictionary assignment). var expression = arguments[0].Expression; return expression is AssignmentExpressionSyntax or CollectionExpressionSyntax ? ParenthesizedExpression(expression) : expression; } else { return InitializerExpression( SyntaxKind.ComplexElementInitializerExpression, OpenBraceToken.WithoutTrivia(), SeparatedList( arguments.Select(a => a.Expression), arguments.GetSeparators()), CloseBraceToken.WithoutTrivia()); } } } }