| File: Rename\LocalConflictVisitor.vb | Web Access |
| Project: src\roslyn\src\Workspaces\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj (Microsoft.CodeAnalysis.VisualBasic.Workspaces) |
' 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.Threading Imports Microsoft.CodeAnalysis.Rename.ConflictEngine Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Rename Friend Class LocalConflictVisitor Inherits VisualBasicSyntaxVisitor Private ReadOnly _tracker As ConflictingIdentifierTracker Private ReadOnly _semanticModel As SemanticModel Private ReadOnly _cancellationToken As CancellationToken Public Sub New(tokenBeingRenamed As SyntaxToken, semanticModel As SemanticModel, cancellationToken As CancellationToken) _tracker = New ConflictingIdentifierTracker(tokenBeingRenamed, CaseInsensitiveComparison.Comparer) _semanticModel = semanticModel _cancellationToken = cancellationToken End Sub Public Overrides Sub DefaultVisit(node As SyntaxNode) For Each child In node.ChildNodes() Visit(child) Next End Sub Private Sub VisitMethodBlockBase(node As MethodBlockBaseSyntax) Dim tokens As New List(Of SyntaxToken) If node.BlockStatement.ParameterList IsNot Nothing Then tokens.AddRange(From parameter In node.BlockStatement.ParameterList.Parameters Select parameter.Identifier.Identifier) End If _tracker.AddIdentifiers(tokens) VisitBlock(node.Statements) _tracker.RemoveIdentifiers(tokens) End Sub Public Overrides Sub VisitMethodBlock(node As MethodBlockSyntax) VisitMethodBlockBase(node) End Sub Public Overrides Sub VisitConstructorBlock(node As ConstructorBlockSyntax) VisitMethodBlockBase(node) End Sub Public Overrides Sub VisitOperatorBlock(node As OperatorBlockSyntax) VisitMethodBlockBase(node) End Sub Public Overrides Sub VisitAccessorBlock(node As AccessorBlockSyntax) VisitMethodBlockBase(node) End Sub Public Overrides Sub VisitQueryExpression(node As QueryExpressionSyntax) Dim tokens As New List(Of SyntaxToken) ' TODO: fully implement handling of all range vars incl. hiding rules. For Each clause In node.Clauses Select Case clause.Kind Case SyntaxKind.FromClause tokens.AddRange(From variable In DirectCast(clause, FromClauseSyntax).Variables Select variable.Identifier.Identifier) End Select Next _tracker.AddIdentifiers(tokens) For Each clause In node.Clauses Visit(clause) Next _tracker.RemoveIdentifiers(tokens) End Sub Private Sub VisitBlock(block As SyntaxList(Of StatementSyntax)) Dim tokens As New List(Of SyntaxToken) For Each statement In block If statement.Kind = SyntaxKind.LocalDeclarationStatement Then Dim declarationStatement = DirectCast(statement, LocalDeclarationStatementSyntax) For Each declarator In declarationStatement.Declarators tokens.AddRange(From i In declarator.Names Select i.Identifier) Next End If Next _tracker.AddIdentifiers(tokens) For Each statement In block Visit(statement) Next _tracker.RemoveIdentifiers(tokens) End Sub Public Overrides Sub VisitSingleLineLambdaExpression(node As SingleLineLambdaExpressionSyntax) Dim tokens As New List(Of SyntaxToken) If node.SubOrFunctionHeader.ParameterList IsNot Nothing Then tokens.AddRange(From parameter In node.SubOrFunctionHeader.ParameterList.Parameters Select parameter.Identifier.Identifier) End If _tracker.AddIdentifiers(tokens) Visit(node.Body) _tracker.RemoveIdentifiers(tokens) End Sub Public Overrides Sub VisitMultiLineLambdaExpression(node As MultiLineLambdaExpressionSyntax) Dim tokens As New List(Of SyntaxToken) If node.SubOrFunctionHeader.ParameterList IsNot Nothing Then tokens.AddRange(From parameter In node.SubOrFunctionHeader.ParameterList.Parameters Select parameter.Identifier.Identifier) End If _tracker.AddIdentifiers(tokens) VisitBlock(node.Statements) _tracker.RemoveIdentifiers(tokens) End Sub Public Overrides Sub VisitForBlock(node As ForBlockSyntax) VisitForOrForEachBlock(node) End Sub Public Overrides Sub VisitForEachBlock(node As ForEachBlockSyntax) VisitForOrForEachBlock(node) End Sub Private Sub VisitForOrForEachBlock(node As ForOrForEachBlockSyntax) Dim tokens As New List(Of SyntaxToken) Dim controlVariable As SyntaxNode If node.ForOrForEachStatement.Kind = SyntaxKind.ForEachStatement Then controlVariable = DirectCast(node.ForOrForEachStatement, ForEachStatementSyntax).ControlVariable Else controlVariable = DirectCast(node.ForOrForEachStatement, ForStatementSyntax).ControlVariable End If If controlVariable.Kind = SyntaxKind.VariableDeclarator Then ' it's only legal to have one name in the variable declarator for for and foreach loops. tokens.Add(DirectCast(controlVariable, VariableDeclaratorSyntax).Names.First().Identifier) Else Dim symbol = _semanticModel.GetSymbolInfo(controlVariable, _cancellationToken).Symbol ' if it is a field we don't care If symbol IsNot Nothing AndAlso symbol.IsKind(SymbolKind.Local) Then Dim local = DirectCast(symbol, ILocalSymbol) ' is this local declared in the for or for each loop? ' if not it was already added to the tracker before. If local.IsFor OrElse local.IsForEach Then If controlVariable.Kind = SyntaxKind.IdentifierName Then tokens.Add(DirectCast(controlVariable, IdentifierNameSyntax).Identifier) Else Debug.Fail($"Unexpected control variable kind '{controlVariable.Kind}'") End If End If End If End If _tracker.AddIdentifiers(tokens) VisitBlock(node.Statements) _tracker.RemoveIdentifiers(tokens) End Sub Public Overrides Sub VisitUsingBlock(node As UsingBlockSyntax) Dim tokens As New List(Of SyntaxToken) ' add all declared variable names to token list For Each usingVariableDeclarator In node.UsingStatement.Variables For Each name In usingVariableDeclarator.Names tokens.Add(name.Identifier) Next Next _tracker.AddIdentifiers(tokens) VisitBlock(node.Statements) _tracker.RemoveIdentifiers(tokens) End Sub Public Overrides Sub VisitCatchBlock(node As CatchBlockSyntax) Dim tokens As New List(Of SyntaxToken) Dim identifierToken = node.CatchStatement.IdentifierName?.Identifier If identifierToken.HasValue Then Dim symbol = _semanticModel.GetSymbolInfo(identifierToken.Value, _cancellationToken).Symbol ' if it is a field we don't care If symbol IsNot Nothing AndAlso symbol.IsKind(SymbolKind.Local) Then Dim local = DirectCast(symbol, ILocalSymbol) ' is this local declared in the for or for each loop? ' if not it was already added to the tracker before. If local.IsCatch Then tokens.Add(identifierToken.Value) End If End If End If _tracker.AddIdentifiers(tokens) VisitBlock(node.Statements) _tracker.RemoveIdentifiers(tokens) End Sub Public ReadOnly Property ConflictingTokens As IEnumerable(Of SyntaxToken) Get Return _tracker.ConflictingTokens End Get End Property End Class End Namespace