File: ConvertForToForEach\VisualBasicConvertForToForEachCodeRefactoringProvider.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.Composition
Imports System.Diagnostics.CodeAnalysis
Imports System.Threading
Imports Microsoft.CodeAnalysis.CodeRefactorings
Imports Microsoft.CodeAnalysis.ConvertForToForEach
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertForToForEach
    <ExportCodeRefactoringProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeRefactoringProviderNames.ConvertForToForEach), [Shared]>
    Friend Class VisualBasicConvertForToForEachCodeRefactoringProvider
        Inherits AbstractConvertForToForEachCodeRefactoringProvider(Of
            StatementSyntax,
            ForBlockSyntax,
            ExpressionSyntax,
            MemberAccessExpressionSyntax,
            TypeSyntax,
            VariableDeclaratorSyntax)
 
        <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
 
        Protected Overrides Function GetTitle() As String
            Return VBFeaturesResources.Convert_to_For_Each
        End Function
 
        Protected Overrides Function GetBodyStatements(forStatement As ForBlockSyntax) As SyntaxList(Of StatementSyntax)
            Return forStatement.Statements
        End Function
 
        Protected Overrides Function IsValidVariableDeclarator(firstVariable As VariableDeclaratorSyntax) As Boolean
            ' we only support local declarations in vb that have a single identifier.  i.e.
            '    dim x = list(i)
            Return firstVariable.Names.Count = 1
        End Function
 
        Protected Overrides Function TryGetForStatementComponents(
                forBlock As ForBlockSyntax,
                ByRef iterationVariable As SyntaxToken,
                ByRef initializer As ExpressionSyntax,
                ByRef memberAccess As MemberAccessExpressionSyntax,
                ByRef stepValueExpressionOpt As ExpressionSyntax,
                cancellationToken As CancellationToken) As Boolean
 
            Dim forStatement As ForStatementSyntax = forBlock.ForStatement
            Dim identifierName = TryCast(forStatement.ControlVariable, IdentifierNameSyntax)
 
            If identifierName IsNot Nothing Then
                iterationVariable = identifierName.Identifier
 
                If forStatement.FromValue IsNot Nothing Then
                    initializer = forStatement.FromValue
 
                    Dim subtraction = TryCast(forStatement.ToValue, BinaryExpressionSyntax)
                    If subtraction?.Kind() = SyntaxKind.SubtractExpression Then
                        Dim subtractionRight = TryCast(subtraction.Right, LiteralExpressionSyntax)
                        If TypeOf subtractionRight?.Token.Value Is Integer AndAlso
                           DirectCast(subtractionRight.Token.Value, Integer) = 1 Then
 
                            memberAccess = TryCast(subtraction.Left, MemberAccessExpressionSyntax)
                            If memberAccess IsNot Nothing Then
                                stepValueExpressionOpt = forStatement.StepClause?.StepValue
                                Return True
                            End If
                        End If
                    End If
                End If
            End If
 
            Return False
        End Function
 
        Protected Overrides Function ConvertForNode(
                currentFor As ForBlockSyntax, typeNode As TypeSyntax,
                foreachIdentifier As SyntaxToken, collectionExpression As ExpressionSyntax, iterationVariableType As ITypeSymbol) As SyntaxNode
 
            Dim forStatement = currentFor.ForStatement
            Return SyntaxFactory.ForEachBlock(
                SyntaxFactory.ForEachStatement(
                    forStatement.ForKeyword,
                    SyntaxFactory.Token(SyntaxKind.EachKeyword),
                    SyntaxFactory.VariableDeclarator(
                        SyntaxFactory.SingletonSeparatedList(SyntaxFactory.ModifiedIdentifier(foreachIdentifier)),
                        If(typeNode IsNot Nothing, SyntaxFactory.SimpleAsClause(typeNode), Nothing),
                        Nothing),
                    SyntaxFactory.Token(SyntaxKind.InKeyword),
                    collectionExpression).WithTriviaFrom(forStatement),
                currentFor.Statements,
                currentFor.NextStatement)
        End Function
    End Class
End Namespace