/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Binding/InitializerSemanticModel.vb
230 строк
13 KB
AlekseyTs
VB: Align design around speculative semantic models with C#. (#64751)
18 окт 2022, 21:51
Не верифицирован
18 окт 2022, 21:51
3f694a3
Код
Авторство
О чём код?
' 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.Runtime.InteropServices Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic Friend NotInheritable Class InitializerSemanticModel Inherits MemberSemanticModel Friend Sub New(root As VisualBasicSyntaxNode, binder As Binder, containingPublicSemanticModel As PublicSemanticModel) MyBase.New(root, binder, containingPublicSemanticModel) End Sub ''' <summary> ''' Creates an InitializerSemanticModel that allows asking semantic questions about an initializer node. ''' </summary> Friend Shared Function Create(containingSemanticModel As SyntaxTreeSemanticModel, binder As DeclarationInitializerBinder) As InitializerSemanticModel Debug.Assert(containingSemanticModel IsNot Nothing) Return New InitializerSemanticModel(binder.Root, binder, containingSemanticModel) End Function ''' <summary> ''' Creates a speculative semantic model that allows asking semantic questions about an initializer node that did not appear in the original source code. ''' </summary> Friend Shared Function CreateSpeculative(parentSemanticModel As SyntaxTreeSemanticModel, root As EqualsValueSyntax, binder As Binder, position As Integer) As SpeculativeSemanticModelWithMemberModel Return New SpeculativeSemanticModelWithMemberModel(parentSemanticModel, position, root, binder) End Function Friend Overrides Function Bind(binder As Binder, node As SyntaxNode, diagnostics As BindingDiagnosticBag) As BoundNode Debug.Assert(binder.IsSemanticModelBinder) Dim boundInitializer As BoundNode = Nothing Select Case node.Kind Case SyntaxKind.FieldDeclaration ' get field symbol If Me.MemberSymbol.Kind = SymbolKind.Field Then Dim fieldSymbol = DirectCast(Me.MemberSymbol, SourceFieldSymbol) boundInitializer = BindInitializer(binder, fieldSymbol.EqualsValueOrAsNewInitOpt, diagnostics) Else Dim propertySymbol = DirectCast(Me.MemberSymbol, SourcePropertySymbol) Dim declSyntax As ModifiedIdentifierSyntax = DirectCast(propertySymbol.Syntax, ModifiedIdentifierSyntax) Dim declarator = DirectCast(declSyntax.Parent, VariableDeclaratorSyntax) Dim initSyntax As VisualBasicSyntaxNode = declarator.AsClause If initSyntax Is Nothing OrElse initSyntax.Kind <> SyntaxKind.AsNewClause Then initSyntax = declarator.Initializer End If boundInitializer = BindInitializer(binder, initSyntax, diagnostics) End If Case SyntaxKind.PropertyStatement ' get property symbol Dim propertySymbol = DirectCast(Me.MemberSymbol, SourcePropertySymbol) Dim declSyntax As PropertyStatementSyntax = DirectCast(propertySymbol.DeclarationSyntax, PropertyStatementSyntax) Dim initSyntax As VisualBasicSyntaxNode = declSyntax.AsClause If initSyntax Is Nothing OrElse initSyntax.Kind <> SyntaxKind.AsNewClause Then initSyntax = declSyntax.Initializer End If boundInitializer = BindInitializer(binder, initSyntax, diagnostics) Case SyntaxKind.Parameter Dim parameterSyntax = DirectCast(node, ParameterSyntax) boundInitializer = BindInitializer(binder, parameterSyntax.Default, diagnostics) Case SyntaxKind.EnumMemberDeclaration Dim enumSyntax = DirectCast(node, EnumMemberDeclarationSyntax) boundInitializer = BindInitializer(binder, enumSyntax.Initializer, diagnostics) Case SyntaxKind.EqualsValue, SyntaxKind.AsNewClause boundInitializer = BindInitializer(binder, node, diagnostics) End Select If boundInitializer IsNot Nothing Then Return boundInitializer Else Return MyBase.Bind(binder, node, diagnostics) End If End Function Private Iterator Function GetInitializedFieldsOrProperties(binder As Binder) As IEnumerable(Of Symbol) Yield Me.MemberSymbol For Each additionalSymbol In binder.AdditionalContainingMembers Yield additionalSymbol Next End Function Private Function BindInitializer(binder As Binder, initializer As SyntaxNode, diagnostics As BindingDiagnosticBag) As BoundNode Dim boundInitializer As BoundNode = Nothing Select Case Me.MemberSymbol.Kind Case SymbolKind.Field ' try to get enum field symbol Dim enumFieldSymbol = TryCast(Me.MemberSymbol, SourceEnumConstantSymbol) If enumFieldSymbol IsNot Nothing Then Debug.Assert(initializer IsNot Nothing) If initializer.Kind = SyntaxKind.EqualsValue Then Dim enumSymbol = DirectCast(Me.MemberSymbol, SourceEnumConstantSymbol) boundInitializer = binder.BindFieldAndEnumConstantInitializer(enumSymbol, DirectCast(initializer, EqualsValueSyntax), isEnum:=True, diagnostics:=diagnostics, constValue:=Nothing) End If Else ' get field symbol Dim fieldSymbol = DirectCast(Me.MemberSymbol, SourceFieldSymbol) Dim boundInitializers = ArrayBuilder(Of BoundInitializer).GetInstance If initializer IsNot Nothing Then ' bind const and non const field initializers the same to get a bound expression back and not a constant value. Dim fields = ImmutableArray.CreateRange(GetInitializedFieldsOrProperties(binder).Cast(Of FieldSymbol)) binder.BindFieldInitializer(fields, initializer, boundInitializers, diagnostics, bindingForSemanticModel:=True) Else binder.BindArrayFieldImplicitInitializer(fieldSymbol, boundInitializers, diagnostics) End If boundInitializer = boundInitializers.First boundInitializers.Free() End If Dim expressionInitializer = TryCast(boundInitializer, BoundExpression) If expressionInitializer IsNot Nothing Then Return New BoundFieldInitializer(initializer, ImmutableArray.Create(DirectCast(Me.MemberSymbol, FieldSymbol)), Nothing, expressionInitializer, binderOpt:=Nothing) End If Case SymbolKind.Property ' get property symbol Dim propertySymbols = ImmutableArray.CreateRange(GetInitializedFieldsOrProperties(binder).Cast(Of PropertySymbol)) Dim boundInitializers = ArrayBuilder(Of BoundInitializer).GetInstance binder.BindPropertyInitializer(propertySymbols, initializer, boundInitializers, diagnostics) boundInitializer = boundInitializers.First boundInitializers.Free() Dim expressionInitializer = TryCast(boundInitializer, BoundExpression) If expressionInitializer IsNot Nothing Then Return New BoundPropertyInitializer(initializer, propertySymbols, Nothing, expressionInitializer, binderOpt:=Nothing) End If Case SymbolKind.Parameter Debug.Assert(initializer IsNot Nothing) If initializer.Kind = SyntaxKind.EqualsValue Then Dim parameterSymbol = DirectCast(Me.RootBinder.ContainingMember, SourceComplexParameterSymbol) boundInitializer = binder.BindParameterDefaultValue(parameterSymbol.Type, DirectCast(initializer, EqualsValueSyntax), diagnostics, constValue:=Nothing) Dim expressionInitializer = TryCast(boundInitializer, BoundExpression) If expressionInitializer IsNot Nothing Then Return New BoundParameterEqualsValue(initializer, parameterSymbol, expressionInitializer) End If End If Case Else Throw ExceptionUtilities.UnexpectedValue(Me.MemberSymbol.Kind) End Select Return boundInitializer End Function Friend Overrides Function GetBoundRoot() As BoundNode ' In initializer the root bound node is sometimes not associated with Me.Root. Get the ' syntax that the root bound node should be associated with. Dim rootSyntax = Me.Root If rootSyntax.Kind = SyntaxKind.FieldDeclaration Then Dim fieldSymbol = TryCast(Me.RootBinder.ContainingMember, SourceFieldSymbol) If fieldSymbol IsNot Nothing Then rootSyntax = If(fieldSymbol.EqualsValueOrAsNewInitOpt, fieldSymbol.Syntax) Else ' 'WithEvents x As Y = ...' Dim propertySymbol = TryCast(Me.RootBinder.ContainingMember, SourcePropertySymbol) Debug.Assert(rootSyntax Is propertySymbol.DeclarationSyntax) Dim propertyNameId = DirectCast(propertySymbol.Syntax, ModifiedIdentifierSyntax) ' serves as an assert Dim declarator = DirectCast(propertyNameId.Parent, VariableDeclaratorSyntax) ' serves as an assert Dim initSyntax As VisualBasicSyntaxNode = declarator.AsClause If initSyntax Is Nothing OrElse initSyntax.Kind <> SyntaxKind.AsNewClause Then initSyntax = declarator.Initializer End If If initSyntax IsNot Nothing Then rootSyntax = initSyntax End If End If ElseIf rootSyntax.Kind = SyntaxKind.PropertyStatement Then Dim declSyntax As PropertyStatementSyntax = DirectCast(rootSyntax, PropertyStatementSyntax) Dim initSyntax As VisualBasicSyntaxNode = declSyntax.AsClause If initSyntax Is Nothing OrElse initSyntax.Kind <> SyntaxKind.AsNewClause Then initSyntax = declSyntax.Initializer End If If initSyntax IsNot Nothing Then rootSyntax = initSyntax End If End If 'TODO - Do parameters need to do anything here? Return GetUpperBoundNode(rootSyntax) End Function Friend Overrides Function TryGetSpeculativeSemanticModelCore(parentModel As SyntaxTreeSemanticModel, position As Integer, initializer As EqualsValueSyntax, <Out> ByRef speculativeModel As PublicSemanticModel) As Boolean Dim binder = Me.GetEnclosingBinder(position) If binder Is Nothing Then speculativeModel = Nothing Return False End If ' wrap the binder with a Speculative binder binder = SpeculativeBinder.Create(binder) speculativeModel = CreateSpeculative(parentModel, initializer, binder, position) Return True End Function Friend Overrides Function TryGetSpeculativeSemanticModelCore(parentModel As SyntaxTreeSemanticModel, position As Integer, statement As ExecutableStatementSyntax, <Out> ByRef speculativeModel As PublicSemanticModel) As Boolean speculativeModel = Nothing Return False End Function Friend Overrides Function TryGetSpeculativeSemanticModelForMethodBodyCore(parentModel As SyntaxTreeSemanticModel, position As Integer, body As MethodBlockBaseSyntax, <Out> ByRef speculativeModel As PublicSemanticModel) As Boolean speculativeModel = Nothing Return False End Function End Class End Namespace