File: src\Analyzers\VisualBasic\CodeFixes\MakeMethodSynchronous\VisualBasicMakeMethodSynchronousCodeFixProvider.vb
Web Access
Project: src\src\Features\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Features.vbproj (Microsoft.CodeAnalysis.VisualBasic.Features)
' 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.
 
Imports System.Collections.Immutable
Imports System.Composition
Imports System.Diagnostics.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.MakeMethodSynchronous
Imports Microsoft.CodeAnalysis.VisualBasic.RemoveAsyncModifier
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.MakeMethodSynchronous
    <ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.MakeMethodSynchronous), [Shared]>
    <ExtensionOrder(After:=PredefinedCodeFixProviderNames.AddImport)>
    Friend Class VisualBasicMakeMethodSynchronousCodeFixProvider
        Inherits AbstractMakeMethodSynchronousCodeFixProvider
 
        Private Const BC42356 As String = NameOf(BC42356) ' This async method lacks 'Await' operators and so will run synchronously.
 
        Private Shared ReadOnly s_diagnosticIds As ImmutableArray(Of String) = ImmutableArray.Create(BC42356)
 
        <ImportingConstructor>
        <SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification:="Used in test code: https://github.com/dotnet/roslyn/issues/42814")>
        Public Sub New()
        End Sub
 
        Public Overrides ReadOnly Property FixableDiagnosticIds As ImmutableArray(Of String)
            Get
                Return s_diagnosticIds
            End Get
        End Property
 
        Protected Overrides Function IsAsyncSupportingFunctionSyntax(node As SyntaxNode) As Boolean
            Return node.IsAsyncSupportedFunctionSyntax()
        End Function
 
        Protected Overrides Function RemoveAsyncTokenAndFixReturnType(methodSymbolOpt As IMethodSymbol, node As SyntaxNode, knownTypes As KnownTaskTypes) As SyntaxNode
            If node.IsKind(SyntaxKind.SingleLineSubLambdaExpression) OrElse
                node.IsKind(SyntaxKind.SingleLineFunctionLambdaExpression) Then
 
                Return RemoveAsyncModifierHelpers.FixSingleLineLambdaExpression(DirectCast(node, SingleLineLambdaExpressionSyntax))
            ElseIf node.IsKind(SyntaxKind.MultiLineSubLambdaExpression) OrElse
                    node.IsKind(SyntaxKind.MultiLineFunctionLambdaExpression) Then
 
                Return RemoveAsyncModifierHelpers.FixMultiLineLambdaExpression(DirectCast(node, MultiLineLambdaExpressionSyntax))
            ElseIf node.IsKind(SyntaxKind.SubBlock) Then
                Return FixSubBlock(DirectCast(node, MethodBlockSyntax))
            Else
                Return FixFunctionBlock(methodSymbolOpt, DirectCast(node, MethodBlockSyntax), knownTypes)
            End If
        End Function
 
        Private Shared Function FixFunctionBlock(methodSymbol As IMethodSymbol, node As MethodBlockSyntax, knownTypes As KnownTaskTypes) As SyntaxNode
            Dim functionStatement = node.SubOrFunctionStatement
 
            ' if this returns Task(of T), then we want to convert this to a T returning function.
            ' if this returns Task, then we want to convert it to a Sub method.
            If methodSymbol.ReturnType.OriginalDefinition.Equals(knownTypes.TaskOfTType) Then
                Dim newAsClause = functionStatement.AsClause.WithType(methodSymbol.ReturnType.GetTypeArguments()(0).GenerateTypeSyntax())
                Dim newFunctionStatement = functionStatement.WithAsClause(newAsClause)
                newFunctionStatement = RemoveAsyncModifierHelpers.RemoveAsyncKeyword(newFunctionStatement)
                Return node.WithSubOrFunctionStatement(newFunctionStatement)
            ElseIf Equals(methodSymbol.ReturnType.OriginalDefinition, knownTypes.TaskType) Then
                ' Convert this to a 'Sub' method.
                Dim subStatement = SyntaxFactory.SubStatement(
                    functionStatement.AttributeLists,
                    functionStatement.Modifiers,
                    SyntaxFactory.Token(SyntaxKind.SubKeyword).WithTriviaFrom(functionStatement.SubOrFunctionKeyword),
                    functionStatement.Identifier,
                    functionStatement.TypeParameterList,
                    functionStatement.ParameterList,
                    functionStatement.AsClause,
                    functionStatement.HandlesClause,
                    functionStatement.ImplementsClause)
 
                subStatement = subStatement.RemoveNode(subStatement.AsClause, SyntaxRemoveOptions.KeepTrailingTrivia)
                subStatement = RemoveAsyncModifierHelpers.RemoveAsyncKeyword(subStatement)
 
                Dim endSubStatement = SyntaxFactory.EndSubStatement(
                    node.EndSubOrFunctionStatement.EndKeyword,
                    SyntaxFactory.Token(SyntaxKind.SubKeyword).WithTriviaFrom(node.EndSubOrFunctionStatement.BlockKeyword))
 
                Return SyntaxFactory.SubBlock(subStatement, node.Statements, endSubStatement)
            Else
                Dim newFunctionStatement = RemoveAsyncModifierHelpers.RemoveAsyncKeyword(functionStatement)
                Return node.WithSubOrFunctionStatement(newFunctionStatement)
            End If
        End Function
 
        Private Shared Function FixSubBlock(node As MethodBlockSyntax) As SyntaxNode
            Dim newSubStatement = RemoveAsyncModifierHelpers.RemoveAsyncKeyword(node.SubOrFunctionStatement)
            Return node.WithSubOrFunctionStatement(newSubStatement)
        End Function
    End Class
End Namespace