/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Binding/LocalBinderBuilder.vb
326 строк
14 KB
Jonathon Marolf
update headers
23 янв 2020, 04:01
Не верифицирован
23 янв 2020, 04:01
91571a3
Код
Авторство
О чём код?
' 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 Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic ''' <summary> ''' The <see cref="LocalBinderBuilder"/> is used to build up the map of all <see cref="Binder"/>s within a method body, and the associated ''' <see cref="VisualBasicSyntaxNode"/>. To do so it traverses all the statements, handling blocks and other ''' statements that create scopes. For efficiency reasons, it does not traverse into ''' expressions. This means that blocks within lambdas and queries are not created. ''' Blocks within lambdas are bound by their own <see cref="LocalBinderBuilder"/> when they are ''' analyzed. ''' ''' For reasons of lifetime management, this type is distinct from the <see ''' cref="BinderFactory"/> ''' which also creates a map from <see cref="VisualBasicSyntaxNode"/> to <see cref="Binder"/>. That type owns it's binders ''' and that type's lifetime is that of the compilation. Therefore we do not store ''' binders local to method bodies in that type's cache. ''' </summary> Friend Class LocalBinderBuilder Inherits VisualBasicSyntaxVisitor Private _nodeMap As ImmutableDictionary(Of SyntaxNode, BlockBaseBinder) Private _listMap As ImmutableDictionary(Of SyntaxList(Of StatementSyntax), BlockBaseBinder) Private ReadOnly _enclosingMethod As MethodSymbol Private _containingBinder As Binder Public Sub New(enclosingMethod As MethodSymbol) _enclosingMethod = enclosingMethod _nodeMap = ImmutableDictionary.Create(Of SyntaxNode, BlockBaseBinder)() _listMap = ImmutableDictionary.Create(Of SyntaxList(Of StatementSyntax), BlockBaseBinder)() End Sub Public Sub New(enclosingMethod As MethodSymbol, nodeMap As ImmutableDictionary(Of SyntaxNode, BlockBaseBinder), listMap As ImmutableDictionary(Of SyntaxList(Of StatementSyntax), BlockBaseBinder)) _enclosingMethod = enclosingMethod _nodeMap = nodeMap _listMap = listMap End Sub Public Sub MakeBinder(node As SyntaxNode, containingBinder As Binder) Dim oldContainingBinder As Binder = Me._containingBinder Me._containingBinder = containingBinder MyBase.Visit(node) Me._containingBinder = oldContainingBinder End Sub Public ReadOnly Property NodeToBinderMap As ImmutableDictionary(Of SyntaxNode, BlockBaseBinder) Get Return _nodeMap End Get End Property Public ReadOnly Property StmtListToBinderMap As ImmutableDictionary(Of SyntaxList(Of StatementSyntax), BlockBaseBinder) Get Return _listMap End Get End Property ' Visit the statements in a statement list. Does not create a containing binder. Private Sub VisitStatementsInList(list As IEnumerable(Of StatementSyntax), currentBinder As BlockBaseBinder) For Each n In list MakeBinder(n, currentBinder) Next End Sub ' Create a binder using the given statement list. Private Sub CreateBinderFromStatementList(list As SyntaxList(Of StatementSyntax), outerBinder As Binder) Dim newBinder = New StatementListBinder(outerBinder, list) _listMap = _listMap.SetItem(list, newBinder) VisitStatementsInList(list, newBinder) End Sub ' Add a binder to the map. Private Sub RememberBinder(node As VisualBasicSyntaxNode, binder As Binder) _nodeMap = _nodeMap.SetItem(node, DirectCast(binder, BlockBaseBinder)) End Sub ''' <summary> ''' Creates binders for top-level executable statements. ''' </summary> Public Overrides Sub VisitCompilationUnit(node As CompilationUnitSyntax) For Each member In node.Members ' Visit methods for non-executable statements are no-ops: MakeBinder(member, _containingBinder) Next 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 Private Sub VisitMethodBlockBase(methodBlock As MethodBlockBaseSyntax) ' Get the right kind of exit kind for this method. Dim exitKind As SyntaxKind Select Case methodBlock.BlockStatement.Kind Case SyntaxKind.SubStatement, SyntaxKind.SubNewStatement exitKind = SyntaxKind.ExitSubStatement Case SyntaxKind.FunctionStatement exitKind = SyntaxKind.ExitFunctionStatement Case SyntaxKind.GetAccessorStatement, SyntaxKind.SetAccessorStatement exitKind = SyntaxKind.ExitPropertyStatement Case SyntaxKind.AddHandlerAccessorStatement, SyntaxKind.RemoveHandlerAccessorStatement, SyntaxKind.RaiseEventAccessorStatement ' this is not an Exit kind (there is no such thing as "Exit AddHandler") ' We just use this so that we get a return label. exitKind = SyntaxKind.EventStatement Case SyntaxKind.OperatorStatement ' Exit Operator does not exist 'exitKind = SyntaxKind.ExitOperatorStatement exitKind = SyntaxKind.OperatorStatement Case Else Throw ExceptionUtilities.UnexpectedValue(methodBlock.BlockStatement.Kind) End Select _containingBinder = New ExitableStatementBinder(_containingBinder, continueKind:=SyntaxKind.None, exitKind:=exitKind) RememberBinder(methodBlock, _containingBinder) CreateBinderFromStatementList(methodBlock.Statements, _containingBinder) End Sub Public Overrides Sub VisitSingleLineLambdaExpression(node As SingleLineLambdaExpressionSyntax) If node Is _enclosingMethod.Syntax Then Dim exitKind As SyntaxKind Select Case node.Kind Case SyntaxKind.SingleLineSubLambdaExpression exitKind = SyntaxKind.ExitSubStatement Case SyntaxKind.SingleLineFunctionLambdaExpression exitKind = SyntaxKind.ExitFunctionStatement Case Else Throw ExceptionUtilities.UnexpectedValue(node.Kind) End Select _containingBinder = New ExitableStatementBinder(_containingBinder, continueKind:=SyntaxKind.None, exitKind:=exitKind) RememberBinder(node, _containingBinder) If node.Kind = SyntaxKind.SingleLineSubLambdaExpression Then ' Even though single line sub lambdas only have a single statement. Create a binder for ' a statement list so that locals can be bound. Note, while locals are not allowed at the top ' level it is useful in the semantic model to bind them. CreateBinderFromStatementList(node.Statements, _containingBinder) End If MakeBinder(node.Body, _containingBinder) Return Else MyBase.VisitSingleLineLambdaExpression(node) : Return End If End Sub Public Overrides Sub VisitMultiLineLambdaExpression(node As MultiLineLambdaExpressionSyntax) If node Is _enclosingMethod.Syntax Then Dim exitKind As SyntaxKind Select Case node.Kind Case SyntaxKind.MultiLineSubLambdaExpression exitKind = SyntaxKind.ExitSubStatement Case SyntaxKind.MultiLineFunctionLambdaExpression exitKind = SyntaxKind.ExitFunctionStatement Case Else Throw ExceptionUtilities.UnexpectedValue(node.Kind) End Select _containingBinder = New ExitableStatementBinder(_containingBinder, continueKind:=SyntaxKind.None, exitKind:=exitKind) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) Return Else MyBase.VisitMultiLineLambdaExpression(node) : Return End If End Sub Public Overrides Sub VisitWhileBlock(node As WhileBlockSyntax) _containingBinder = New ExitableStatementBinder(_containingBinder, continueKind:=SyntaxKind.ContinueWhileStatement, exitKind:=SyntaxKind.ExitWhileStatement) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitUsingBlock(node As UsingBlockSyntax) _containingBinder = New UsingBlockBinder(_containingBinder, node) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitSyncLockBlock(node As SyncLockBlockSyntax) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitWithBlock(node As WithBlockSyntax) _containingBinder = New WithBlockBinder(_containingBinder, node) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitSingleLineIfStatement(node As SingleLineIfStatementSyntax) CreateBinderFromStatementList(node.Statements, _containingBinder) MakeBinder(node.ElseClause, _containingBinder) End Sub Public Overrides Sub VisitSingleLineElseClause(node As SingleLineElseClauseSyntax) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitMultiLineIfBlock(node As MultiLineIfBlockSyntax) CreateBinderFromStatementList(node.Statements, _containingBinder) For Each elseifBlock In node.ElseIfBlocks MakeBinder(elseifBlock, _containingBinder) Next MakeBinder(node.ElseBlock, _containingBinder) End Sub Public Overrides Sub VisitElseBlock(node As ElseBlockSyntax) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitElseIfBlock(node As ElseIfBlockSyntax) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitTryBlock(node As TryBlockSyntax) _containingBinder = New ExitableStatementBinder(_containingBinder, continueKind:=SyntaxKind.None, exitKind:=SyntaxKind.ExitTryStatement) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) For Each catchBlock In node.CatchBlocks MakeBinder(catchBlock, _containingBinder) Next MakeBinder(node.FinallyBlock, _containingBinder) End Sub Public Overrides Sub VisitCatchBlock(node As CatchBlockSyntax) _containingBinder = New CatchBlockBinder(_containingBinder, node) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitFinallyBlock(node As FinallyBlockSyntax) _containingBinder = New FinallyBlockBinder(_containingBinder) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitSelectBlock(node As SelectBlockSyntax) _containingBinder = New ExitableStatementBinder(_containingBinder, continueKind:=SyntaxKind.None, exitKind:=SyntaxKind.ExitSelectStatement) RememberBinder(node, _containingBinder) For Each caseBlock In node.CaseBlocks MakeBinder(caseBlock, _containingBinder) Next End Sub Public Overrides Sub VisitCaseBlock(node As CaseBlockSyntax) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitDoLoopBlock(node As DoLoopBlockSyntax) _containingBinder = New ExitableStatementBinder(_containingBinder, continueKind:=SyntaxKind.ContinueDoStatement, exitKind:=SyntaxKind.ExitDoStatement) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitForBlock(node As ForBlockSyntax) _containingBinder = New ForOrForEachBlockBinder(_containingBinder, node) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub Public Overrides Sub VisitForEachBlock(node As ForEachBlockSyntax) _containingBinder = New ForOrForEachBlockBinder(_containingBinder, node) RememberBinder(node, _containingBinder) CreateBinderFromStatementList(node.Statements, _containingBinder) End Sub End Class End Namespace