diff --git a/src/Features/Core/Portable/MakeMethodAsynchronous/AbstractMakeMethodAsynchronousCodeFixProvider.cs b/src/Features/Core/Portable/MakeMethodAsynchronous/AbstractMakeMethodAsynchronousCodeFixProvider.cs index a86f0a5f43629f11fcb2cbbc98708ef2b96f9ff8..e2aff63b855087c89af5f9c7b389f77e7a1cbfbe 100644 --- a/src/Features/Core/Portable/MakeMethodAsynchronous/AbstractMakeMethodAsynchronousCodeFixProvider.cs +++ b/src/Features/Core/Portable/MakeMethodAsynchronous/AbstractMakeMethodAsynchronousCodeFixProvider.cs @@ -34,6 +34,19 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) } var semanticModel = await context.Document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var compilation = semanticModel.Compilation; + + // Find the symbols for Task, Task and ValueTask. Note that the first + // two are mandatory (since we need them to generate the return types for our + // method if we convert it. The last is optional. It is only needed to know + // if our member is already Task-Like, and that functionality recognizes + // ValueTask if it is available, but does not care if it is not. + var (taskType, taskOfTType, valueTaskOfTTypeOpt) = GetTaskTypes(compilation); + if (taskType == null || taskOfTType == null) + { + return; + } + var symbol = semanticModel.GetDeclaredSymbol(node, cancellationToken) as IMethodSymbol; // If it's a void returning method, offer to keep the void return type, or convert to @@ -60,6 +73,15 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) } } + private (INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTTypeOpt) GetTaskTypes(Compilation compilation) + { + var taskType = compilation.GetTypeByMetadataName("System.Threading.Tasks.Task"); + var taskOfTType = compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1"); + var valueTaskOfTType = compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask`1"); + + return (taskType, taskOfTType, valueTaskOfTType); + } + protected abstract string GetMakeAsyncTaskFunctionResource(); protected abstract string GetMakeAsyncVoidFunctionResource(); @@ -128,9 +150,7 @@ private SyntaxNode GetContainingFunction(Diagnostic diagnostic, CancellationToke SyntaxNode node, CancellationToken cancellationToken) { var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); - var taskType = compilation.GetTypeByMetadataName("System.Threading.Tasks.Task"); - var taskOfTType = compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1"); - var valueTaskOfTType = compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask`1"); + var (taskType, taskOfTType, valueTaskOfTType) = GetTaskTypes(compilation); var newNode = AddAsyncTokenAndFixReturnType(keepVoid, methodSymbolOpt, node, taskType, taskOfTType, valueTaskOfTType) .WithAdditionalAnnotations(Formatter.Annotation);