/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Analyzers/CSharp/CodeFixes/MakeStatementAsynchronous/CSharpMakeStatementAsynchronousCodeFixProvider.cs
111 строк
5 KB
Cyrus Najmabadi
Reapply "Update methods to be `async`." (#81808)
31 дек 2025, 02:04
31 дек 2025, 02:04
ba729ad
Код
Авторство
О чём код?
// 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.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.MakeStatementAsynchronous; using static CSharpSyntaxTokens; [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.MakeStatementAsynchronous), Shared] [method: ImportingConstructor] [method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] internal sealed class CSharpMakeStatementAsynchronousCodeFixProvider() : SyntaxEditorBasedCodeFixProvider { // error CS8414: foreach statement cannot operate on variables of type 'IAsyncEnumerable<int>' because 'IAsyncEnumerable<int>' does not contain a public instance definition for 'GetEnumerator'. Did you mean 'await foreach'? // error CS8418: 'IAsyncDisposable': type used in a using statement must implement 'System.IDisposable'. Did you mean 'await using' rather than 'using'? public sealed override ImmutableArray<string> FixableDiagnosticIds => ["CS8414", "CS8418"]; public override async Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.First(); var root = await context.Document.GetRequiredSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var node = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true); var constructToFix = TryGetStatementToFix(node); if (constructToFix == null) { return; } RegisterCodeFix(context, CSharpCodeFixesResources.Add_await, nameof(CSharpCodeFixesResources.Add_await)); } protected override async Task FixAllAsync( Document document, ImmutableArray<Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) { foreach (var diagnostic in diagnostics) { var node = diagnostic.Location.FindNode(getInnermostNodeForTie: true, cancellationToken); var statementToFix = TryGetStatementToFix(node); if (statementToFix != null) { MakeStatementAsynchronous(editor, statementToFix); } } } private static void MakeStatementAsynchronous(SyntaxEditor editor, SyntaxNode statementToFix) { SyntaxNode newStatement; switch (statementToFix) { case ForEachStatementSyntax forEach: newStatement = forEach .WithForEachKeyword(forEach.ForEachKeyword.WithLeadingTrivia()) .WithAwaitKeyword(AwaitKeyword.WithLeadingTrivia(forEach.GetLeadingTrivia())); break; case ForEachVariableStatementSyntax forEachDeconstruction: newStatement = forEachDeconstruction .WithForEachKeyword(forEachDeconstruction.ForEachKeyword.WithLeadingTrivia()) .WithAwaitKeyword(AwaitKeyword.WithLeadingTrivia(forEachDeconstruction.GetLeadingTrivia())); break; case UsingStatementSyntax usingStatement: newStatement = usingStatement .WithUsingKeyword(usingStatement.UsingKeyword.WithLeadingTrivia()) .WithAwaitKeyword(AwaitKeyword.WithLeadingTrivia(usingStatement.GetLeadingTrivia())); break; case LocalDeclarationStatementSyntax localDeclaration: newStatement = localDeclaration .WithUsingKeyword(localDeclaration.UsingKeyword.WithLeadingTrivia()) .WithAwaitKeyword(AwaitKeyword.WithLeadingTrivia(localDeclaration.GetLeadingTrivia())); break; default: return; } editor.ReplaceNode(statementToFix, newStatement); } private static SyntaxNode? TryGetStatementToFix(SyntaxNode node) { if (node.Parent is (kind: SyntaxKind.ForEachStatement or SyntaxKind.ForEachVariableStatement or SyntaxKind.UsingStatement)) { return node.Parent; } if (node is LocalDeclarationStatementSyntax localDeclaration && localDeclaration.UsingKeyword != default) { return node; } return null; } }