/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Binding/Binder_Utils.vb
1 777 строк
96 KB
AlekseyTs
VB: Recognize and check an `unmanaged` constraint (#75665)
06 ноя 2024, 01:45
Не верифицирован
06 ноя 2024, 01:45
f97c50e
Код
Авторство
О чём код?
' 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.CompilerServices Imports System.Runtime.InteropServices Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic ' Utilities for decoding syntax for use in binding. Partial Friend Class Binder ''' <summary> ''' If the identifier has a type character, report an error on it. ''' </summary> Public Shared Sub DisallowTypeCharacter(identifier As SyntaxToken, diagBag As BindingDiagnosticBag, Optional errid As ERRID = ERRID.ERR_TypecharNotallowed) If (identifier.GetTypeCharacter() <> TypeCharacter.None) Then ReportDiagnostic(diagBag, identifier, errid) End If End Sub Public Shared Function DecodeVariance(varianceKeywordOpt As SyntaxToken) As VarianceKind Select Case varianceKeywordOpt.Kind Case SyntaxKind.None Return VarianceKind.None Case SyntaxKind.InKeyword Return VarianceKind.In Case SyntaxKind.OutKeyword Return VarianceKind.Out Case Else Throw ExceptionUtilities.UnexpectedValue(varianceKeywordOpt.Kind) End Select End Function ''' <summary> ''' Given a list of keywords and a set of keywords kinds to search, return the first keyword ''' in the list, if any, that matches one of the keyword kinds. ''' </summary> Public Shared Function FindFirstKeyword(syntax As SyntaxTokenList, ParamArray keywordKinds As SyntaxKind()) As SyntaxToken For Each keywordSyntax In syntax If Array.IndexOf(keywordKinds, keywordSyntax.Kind) >= 0 Then Return keywordSyntax End If Next Return Nothing End Function ' An array consisting of just the Friend keyword. Private Shared ReadOnly s_friendKeyword As SyntaxKind() = {SyntaxKind.FriendKeyword} ' Report an error on the first keyword to match one of the given kinds. Public Sub ReportModifierError(modifiers As SyntaxTokenList, errid As ERRID, diagBag As DiagnosticBag, ParamArray keywordKinds As SyntaxKind()) Dim badKeyword = FindFirstKeyword(modifiers, keywordKinds) ' Special case: Report "Protected Friend" as error combination if ' Protected is bad and both Protected and Friend found inside modifiers. If badKeyword.Kind = SyntaxKind.ProtectedKeyword Then Dim friendToken = FindFirstKeyword(modifiers, s_friendKeyword) If friendToken.Kind <> SyntaxKind.None Then Dim startLoc As Integer = Math.Min(badKeyword.SpanStart, friendToken.SpanStart) Dim endLoc As Integer = Math.Max(badKeyword.Span.End, friendToken.Span.End) Dim location = Me.SyntaxTree.GetLocation(New TextSpan(startLoc, endLoc - startLoc)) ReportDiagnostic(diagBag, location, errid, badKeyword.ToString() & " " & friendToken.ToString()) Return End If End If ' Normal case. ReportDiagnostic(diagBag, badKeyword, errid, badKeyword.ToString()) End Sub ''' <summary> ''' Map syntax kind of a modifier keyword to SourceMemberFlags value ''' </summary> Friend Shared Function MapKeywordToFlag(syntax As SyntaxToken) As SourceMemberFlags Select Case syntax.Kind Case SyntaxKind.PrivateKeyword : Return SourceMemberFlags.Private Case SyntaxKind.FriendKeyword : Return SourceMemberFlags.Friend Case SyntaxKind.ProtectedKeyword : Return SourceMemberFlags.Protected Case SyntaxKind.PublicKeyword : Return SourceMemberFlags.Public Case SyntaxKind.SharedKeyword : Return SourceMemberFlags.Shared Case SyntaxKind.ReadOnlyKeyword : Return SourceMemberFlags.ReadOnly Case SyntaxKind.WriteOnlyKeyword : Return SourceMemberFlags.WriteOnly Case SyntaxKind.OverloadsKeyword : Return SourceMemberFlags.Overloads Case SyntaxKind.OverridableKeyword : Return SourceMemberFlags.Overridable Case SyntaxKind.MustOverrideKeyword : Return SourceMemberFlags.MustOverride Case SyntaxKind.NotOverridableKeyword : Return SourceMemberFlags.NotOverridable Case SyntaxKind.OverridesKeyword : Return SourceMemberFlags.Overrides Case SyntaxKind.ShadowsKeyword : Return SourceMemberFlags.Shadows Case SyntaxKind.ConstKeyword : Return SourceMemberFlags.Const Case SyntaxKind.StaticKeyword : Return SourceMemberFlags.Static Case SyntaxKind.DefaultKeyword : Return SourceMemberFlags.Default Case SyntaxKind.WithEventsKeyword : Return SourceMemberFlags.WithEvents Case SyntaxKind.WideningKeyword : Return SourceMemberFlags.Widening Case SyntaxKind.NarrowingKeyword : Return SourceMemberFlags.Narrowing Case SyntaxKind.PartialKeyword : Return SourceMemberFlags.Partial Case SyntaxKind.DimKeyword : Return SourceMemberFlags.Dim Case SyntaxKind.MustInheritKeyword : Return SourceMemberFlags.MustInherit Case SyntaxKind.NotInheritableKeyword : Return SourceMemberFlags.NotInheritable Case SyntaxKind.AsyncKeyword : Return SourceMemberFlags.Async Case SyntaxKind.IteratorKeyword : Return SourceMemberFlags.Iterator Case Else #If DEBUG Then ' this case should only be reached for invalid code (invalid == error, not just warnings) ' all possible modifiers should have been handled above. Debug.Assert(syntax.ContainsDiagnostics) Dim hasAtLeastOneSyntaxError As Boolean = False For Each diag In syntax.Errors If diag.Severity = DiagnosticSeverity.Error Then hasAtLeastOneSyntaxError = True Exit For End If Next Debug.Assert(hasAtLeastOneSyntaxError) #End If Return SourceMemberFlags.None End Select End Function ''' <summary> ''' Decodes a set of modifier flags, reported any errors with the flags. ''' </summary> ''' <param name="syntax">The syntax list of the modifiers.</param> ''' <param name="allowableModifiers">A bit-flag of the allowable modifiers. If a bit isn't set, an error occurs.</param> ''' <param name="errIdBadModifier">Error ID to report if a bad modifier is found.</param> ''' <param name="defaultAccessibility">The default accessibility. </param> ''' <returns>Flags for the modifiers.</returns> Public Function DecodeModifiers(syntax As SyntaxTokenList, allowableModifiers As SourceMemberFlags, errIdBadModifier As ERRID, defaultAccessibility As Accessibility, diagBag As DiagnosticBag) As MemberModifiers Dim foundModifiers As SourceMemberFlags = Nothing Dim privateProtectedToken As SyntaxToken = Nothing Dim privateOverridableModifier As SyntaxToken = Nothing Dim privateMustOverrideModifier As SyntaxToken = Nothing Dim privateNotOverridableModifier As SyntaxToken = Nothing ' Go through each modifiers, accumulating flags of what we've seen and reporting errors. For Each keywordSyntax In syntax Dim currentModifier As SourceMemberFlags = MapKeywordToFlag(keywordSyntax) If currentModifier = SourceMemberFlags.None Then Continue For End If ' Report errors with the modifier If (currentModifier And allowableModifiers) = 0 Then ReportDiagnostic(diagBag, keywordSyntax, errIdBadModifier, keywordSyntax.ToString()) ElseIf (currentModifier And foundModifiers) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_DuplicateSpecifier) ElseIf (currentModifier And SourceMemberFlags.AllAccessibilityModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.AllAccessibilityModifiers) <> 0 AndAlso Not ((foundModifiers Or currentModifier) And SourceMemberFlags.AllAccessibilityModifiers) = (SourceMemberFlags.Protected Or SourceMemberFlags.Friend) AndAlso Not (((foundModifiers Or currentModifier) And SourceMemberFlags.AllAccessibilityModifiers) = (SourceMemberFlags.Protected Or SourceMemberFlags.Private)) Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_DuplicateAccessCategoryUsed) ElseIf (currentModifier And SourceMemberFlags.AllOverrideModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.AllOverrideModifiers) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_DuplicateModifierCategoryUsed) ElseIf (currentModifier And SourceMemberFlags.AllWriteabilityModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.AllWriteabilityModifiers) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_DuplicateWriteabilityCategoryUsed) ElseIf (currentModifier And SourceMemberFlags.AllConversionModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.AllConversionModifiers) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_DuplicateConversionCategoryUsed) ElseIf (currentModifier And SourceMemberFlags.AllShadowingModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.AllShadowingModifiers) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_BadSpecifierCombo2, "Overloads", "Shadows") ElseIf (currentModifier And (SourceMemberFlags.Overrides Or SourceMemberFlags.Overridable)) <> 0 AndAlso (foundModifiers And (SourceMemberFlags.Overrides Or SourceMemberFlags.Overridable)) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_OverridesImpliesOverridable) ElseIf (currentModifier And SourceMemberFlags.PrivateOverridableModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.PrivateOverridableModifiers) <> 0 Then privateOverridableModifier = keywordSyntax foundModifiers = foundModifiers Or currentModifier ElseIf (currentModifier And SourceMemberFlags.ShadowsAndOverrides) <> 0 AndAlso (foundModifiers And SourceMemberFlags.ShadowsAndOverrides) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_BadSpecifierCombo2, "Overrides", "Shadows") ElseIf (currentModifier And SourceMemberFlags.PrivateMustOverrideModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.PrivateMustOverrideModifiers) <> 0 Then privateMustOverrideModifier = keywordSyntax foundModifiers = foundModifiers Or currentModifier ElseIf (currentModifier And SourceMemberFlags.PrivateNotOverridableModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.PrivateNotOverridableModifiers) <> 0 Then privateNotOverridableModifier = keywordSyntax foundModifiers = foundModifiers Or currentModifier ElseIf (currentModifier And (SourceMemberFlags.Iterator Or SourceMemberFlags.WriteOnly)) <> 0 AndAlso (foundModifiers And (SourceMemberFlags.Iterator Or SourceMemberFlags.WriteOnly)) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_BadSpecifierCombo2, "Iterator", "WriteOnly") ElseIf (currentModifier And SourceMemberFlags.TypeInheritModifiers) <> 0 AndAlso (foundModifiers And SourceMemberFlags.TypeInheritModifiers) <> 0 Then ReportDiagnostic(diagBag, keywordSyntax, ERRID.ERR_BadSpecifierCombo2, "MustInherit", "NotInheritable") ' Note: Need to be present both MustInherit & NotInheritable for properly reporting #30926 foundModifiers = foundModifiers Or currentModifier Else If currentModifier = SourceMemberFlags.Private OrElse currentModifier = SourceMemberFlags.Protected Then privateProtectedToken = keywordSyntax End If foundModifiers = foundModifiers Or currentModifier End If Next ' Convert the accessibility modifiers into accessibility. Dim access As Accessibility If (foundModifiers And SourceMemberFlags.Public) <> 0 Then access = Accessibility.Public ElseIf (foundModifiers And (SourceMemberFlags.Friend Or SourceMemberFlags.Protected)) = (SourceMemberFlags.Friend Or SourceMemberFlags.Protected) Then access = Accessibility.ProtectedOrFriend ElseIf (foundModifiers And (SourceMemberFlags.Private Or SourceMemberFlags.Protected)) = (SourceMemberFlags.Private Or SourceMemberFlags.Protected) Then access = Accessibility.ProtectedAndFriend InternalSyntax.Parser.CheckFeatureAvailability( diagBag, privateProtectedToken.GetLocation(), DirectCast(privateProtectedToken.SyntaxTree, VisualBasicSyntaxTree).Options.LanguageVersion, InternalSyntax.Feature.PrivateProtected) ElseIf (foundModifiers And SourceMemberFlags.Friend) <> 0 Then access = Accessibility.Friend ElseIf (foundModifiers And SourceMemberFlags.Protected) <> 0 Then access = Accessibility.Protected ElseIf (foundModifiers And SourceMemberFlags.Private) <> 0 Then access = Accessibility.Private Else access = defaultAccessibility End If If access = Accessibility.Private Then If (foundModifiers And SourceMemberFlags.Overridable) <> 0 Then ReportDiagnostic(diagBag, privateOverridableModifier, ERRID.ERR_BadSpecifierCombo2, "Private", "Overridable") ElseIf (foundModifiers And SourceMemberFlags.MustOverride) <> 0 Then ReportDiagnostic(diagBag, privateMustOverrideModifier, ERRID.ERR_BadSpecifierCombo2, "Private", "MustOverride") ElseIf (foundModifiers And SourceMemberFlags.NotOverridable) <> 0 Then ReportDiagnostic(diagBag, privateNotOverridableModifier, ERRID.ERR_BadSpecifierCombo2, "Private", "NotOverridable") End If foundModifiers = foundModifiers And Not (SourceMemberFlags.Overridable Or SourceMemberFlags.MustOverride Or SourceMemberFlags.NotOverridable) End If ' Add accessibility into the flags. Return New MemberModifiers(foundModifiers, DirectCast(access, SourceMemberFlags)) End Function ''' <summary> ''' Decode a list of parameter modifiers, and return the flags associated with it. ''' </summary> Private Shared Function DecodeParameterModifiers(container As Symbol, modifiers As SyntaxTokenList, checkModifier As CheckParameterModifierDelegate, diagBag As BindingDiagnosticBag) As SourceParameterFlags Dim flags As SourceParameterFlags = Nothing ' Go through each modifiers, accumulating flags of what we've seen and reporting errors. For Each keywordSyntax In modifiers Dim foundFlag As SourceParameterFlags Select Case keywordSyntax.Kind Case SyntaxKind.ByRefKeyword : foundFlag = SourceParameterFlags.ByRef Case SyntaxKind.ByValKeyword : foundFlag = SourceParameterFlags.ByVal Case SyntaxKind.OptionalKeyword : foundFlag = SourceParameterFlags.Optional Case SyntaxKind.ParamArrayKeyword : foundFlag = SourceParameterFlags.ParamArray End Select ' Report errors with the modifier If checkModifier IsNot Nothing Then ' check modifier will clear invalid flags foundFlag = checkModifier(container, keywordSyntax, foundFlag, diagBag) End If flags = flags Or foundFlag Next Return flags End Function ''' <summary> ''' Create the Nullable version of a type. ''' </summary> Public Function CreateNullableOf(typeArgument As TypeSymbol, syntax As VisualBasicSyntaxNode, syntaxTypeArgument As VisualBasicSyntaxNode, diagBag As BindingDiagnosticBag) As NamedTypeSymbol ' Get the Nullable type Dim nullableType As NamedTypeSymbol = DirectCast(GetSpecialType(SpecialType.System_Nullable_T, syntax, diagBag), NamedTypeSymbol) ' Construct the Nullable(Of T). Dim constructedType = nullableType.Construct(ImmutableArray.Create(typeArgument)) ' Validate the type argument meets the Structure constraint on the Nullable type. If ShouldCheckConstraints Then Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance() Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing constructedType.CheckConstraints(Compilation.LanguageVersion, diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=GetNewCompoundUseSiteInfo(diagBag)) If useSiteDiagnosticsBuilder IsNot Nothing Then diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder) End If For Each pair In diagnosticsBuilder diagBag.Add(pair.UseSiteInfo, syntaxTypeArgument.GetLocation()) Next diagnosticsBuilder.Free() End If Return constructedType End Function Public Function GetNewCompoundUseSiteInfo(futureDestination As BindingDiagnosticBag) As CompoundUseSiteInfo(Of AssemblySymbol) Return New CompoundUseSiteInfo(Of AssemblySymbol)(futureDestination, Compilation.Assembly) End Function ''' <summary> ''' Possible create the array version of type, given the element type and the array modifier syntax. ''' </summary> Public Function ApplyArrayRankSpecifiersToType(elementType As TypeSymbol, arrayModifierSyntax As SyntaxList(Of ArrayRankSpecifierSyntax), diagnostics As BindingDiagnosticBag) As TypeSymbol Dim currentType As TypeSymbol = elementType ' Array modifiers must be handled in reverse order, that's the language syntax. For i As Integer = arrayModifierSyntax.Count - 1 To 0 Step -1 ' Rank of the array is the number of commas, plus one. Dim arrayModifier = arrayModifierSyntax(i) If arrayModifier.Rank > 32 Then ReportDiagnostic(diagnostics, arrayModifier, ERRID.ERR_ArrayRankLimit) End If currentType = ArrayTypeSymbol.CreateVBArray(currentType, Nothing, arrayModifier.Rank, Compilation) Next Return currentType End Function ''' <summary> ''' Possibly create the array version of type, given the element type and the array modifier syntax. ''' </summary> Public Function ApplyArrayRankSpecifiersAndBoundsToType(elementType As TypeSymbol, arrayModifierSyntax As SyntaxList(Of ArrayRankSpecifierSyntax), arrayBoundsOpt As ArgumentListSyntax, diagnostics As BindingDiagnosticBag) As TypeSymbol Dim currentType As TypeSymbol = elementType ' Array modifiers must be handled in reverse order, that's the language syntax. currentType = ApplyArrayRankSpecifiersToType(elementType, arrayModifierSyntax, diagnostics) ' Array bounds must be handled in reverse order, that's the language syntax. If arrayBoundsOpt IsNot Nothing Then Dim rank As Integer = arrayBoundsOpt.Arguments.Count If rank = 0 Then rank = 1 End If If rank > 32 Then ReportDiagnostic(diagnostics, arrayBoundsOpt, ERRID.ERR_ArrayRankLimit) End If currentType = ArrayTypeSymbol.CreateVBArray(currentType, Nothing, rank, Compilation) End If Return currentType End Function ''' <summary> ''' Create the array version of type, given the element type and the array modifier syntax. Throws if ''' there aren't any array modifiers and the result is not an array type. ''' </summary> Public Function CreateArrayOf(elementType As TypeSymbol, arrayModifierSyntax As SyntaxList(Of ArrayRankSpecifierSyntax), arrayBoundsOpt As ArgumentListSyntax, diagnostics As BindingDiagnosticBag) As ArrayTypeSymbol Debug.Assert(arrayModifierSyntax.Count > 0 OrElse arrayBoundsOpt IsNot Nothing) Return DirectCast(ApplyArrayRankSpecifiersAndBoundsToType(elementType, arrayModifierSyntax, arrayBoundsOpt, diagnostics), ArrayTypeSymbol) End Function ''' <summary> ''' Given an identifier and an As clause, return true if the identifier does not have a type ''' declared for it (e.g., no type character and no as clause). ''' </summary> Private Shared Function HasDefaultType(identifierSyntax As SyntaxToken, asClauseOptSyntax As AsClauseSyntax) As Boolean Return (identifierSyntax.GetTypeCharacter() = TypeCharacter.None AndAlso asClauseOptSyntax Is Nothing) End Function ''' <summary> ''' Given an identifier and an As clause, return true if the identifier does not have a type ''' declared for it (e.g., no type character and no as clause). ''' </summary> Private Shared Function HasDefaultType(identifierSyntax As ModifiedIdentifierSyntax, asClauseOptSyntax As AsClauseSyntax) As Boolean Return HasDefaultType(identifierSyntax.Identifier, asClauseOptSyntax) End Function ''' <summary> ''' Given an identifier, return true if the identifier declares an array. ''' (e.g., identifier specifies ()) ''' </summary> Public Shared Function IsArrayType(identifierSyntax As ModifiedIdentifierSyntax) As Boolean Return identifierSyntax.ArrayBounds IsNot Nothing OrElse identifierSyntax.ArrayRankSpecifiers.Count > 0 End Function ''' <summary> ''' Flags to specify where the decoding of the modified identifier's type happens. ''' </summary> <Flags()> Public Enum ModifiedIdentifierTypeDecoderContext ''' <summary> ''' No context given (default). ''' </summary> None = 0 ''' <summary> ''' Modified identifier appeared in a lambda declaration. ''' </summary> LambdaType = 1 << 1 ''' <summary> ''' Modified identifier appeared in a local declaration. ''' </summary> LocalType = 1 << 2 ''' <summary> ''' Modified identifier appeared in a field declaration. ''' </summary> FieldType = 1 << 3 ''' <summary> ''' Modified identifier appeared in a parameter. ''' </summary> ParameterType = 1 << 4 ''' <summary> ''' Modified identifier appeared in a query range variable declaration. ''' </summary> QueryRangeVariableType = 1 << 5 ''' <summary> ''' Combined flag to express that a modified identifier appeared in a local or field declaration. ''' </summary> LocalOrFieldType = LocalType Or FieldType ''' <summary> ''' Combined flag to express that a modified identifier appeared in a parameter of a lambda. ''' </summary> LambdaParameterType = LambdaType Or ParameterType StaticLocalType = 1 << 6 End Enum ''' <summary> ''' Given a modified identifier and a type, return the actual type to use. Applies the type character ''' and type modifiers to the given type. ''' </summary> ''' <param name="modifiedIdentifier">The modified identifier.</param> ''' <param name="asClauseOrValueType">Bound type after the As or a type from the initializing value expression. Can be nothing if no type was supplied.</param> ''' <param name="asClauseSyntaxOpt">If specified then it is the syntax for the as clause and the type is the bound type from this syntax.</param> ''' <param name="getRequireTypeDiagnosticInfoFunc">Delegate to get diagnostic info to generate if a required type is missing (Option Strict On/Custom) </param> ''' <returns>The type, as modified by the type character, type modifiers. Uses Object as default if needed.</returns> ''' <remarks></remarks> Public Function DecodeModifiedIdentifierType(modifiedIdentifier As ModifiedIdentifierSyntax, asClauseOrValueType As TypeSymbol, asClauseSyntaxOpt As AsClauseSyntax, initializerSyntaxOpt As VisualBasicSyntaxNode, getRequireTypeDiagnosticInfoFunc As Func(Of DiagnosticInfo), diagBag As BindingDiagnosticBag, Optional decoderContext As ModifiedIdentifierTypeDecoderContext = ModifiedIdentifierTypeDecoderContext.None ) As TypeSymbol Dim baseType As TypeSymbol = DecodeIdentifierType(modifiedIdentifier.Identifier, asClauseOrValueType, getRequireTypeDiagnosticInfoFunc, diagBag, decoderContext) ' Create nullable type. If modifiedIdentifier.Nullable.Node IsNot Nothing Then If asClauseSyntaxOpt IsNot Nothing Then If asClauseSyntaxOpt.Type.Kind = SyntaxKind.NullableType Then ' Special case error for e.g.: "x? as Integer?" ReportDiagnostic(diagBag, asClauseSyntaxOpt, ERRID.ERR_CantSpecifyNullableOnBoth) ' Return the type from the "as" clause, rather than creating a ' second nullable type below (since the user probably intended ' "x? as Integer?" to represent Integer? rather than Integer??). Return baseType ElseIf asClauseSyntaxOpt.Kind = SyntaxKind.AsNewClause Then ReportDiagnostic(diagBag, asClauseSyntaxOpt, ERRID.ERR_CantSpecifyAsNewAndNullable) ElseIf asClauseOrValueType.IsArrayType Then ' ReportDiagnostic(diagBag, asClauseSyntaxOpt, ERRID.ERR_CantSpecifyArrayAndNullableOnBoth) End If End If If asClauseOrValueType Is Nothing AndAlso baseType.IsObjectType() Then ' We didn't have a type specified and ended up with Object, ' which means that we didn't have type character as well. Debug.Assert(asClauseSyntaxOpt Is Nothing) If (decoderContext And ModifiedIdentifierTypeDecoderContext.ParameterType) <> 0 Then ReportDiagnostic(diagBag, modifiedIdentifier, ERRID.ERR_NullableParameterMustSpecifyType) ElseIf (decoderContext And ModifiedIdentifierTypeDecoderContext.LocalOrFieldType) <> 0 AndAlso ((decoderContext And ModifiedIdentifierTypeDecoderContext.StaticLocalType) <> 0 OrElse (initializerSyntaxOpt Is Nothing AndAlso modifiedIdentifier.ArrayBounds Is Nothing)) AndAlso OptionInfer Then ' Note: fields do not support Option Infer On / local type inference, but Dev10 shared the error ' reporting between locals and fields like Roslyn does. So these error will also be shown (and they make ' sense) for fields in case Option Infer is On. ' If option infer is off, variable declarations without an AsClause are explicitly ' set to Object, but this message should only be shown for when the type is implicitly system.object ReportDiagnostic(diagBag, modifiedIdentifier, ERRID.ERR_NullableImplicit) End If ElseIf Not baseType.IsValueType Then ' Trying to make a nullable reference type. ReportDiagnostic(diagBag, modifiedIdentifier, ERRID.ERR_BadTypeArgForStructConstraintNull, baseType) Else baseType = CreateNullableOf(baseType, modifiedIdentifier, If(asClauseSyntaxOpt IsNot Nothing, asClauseSyntaxOpt.Type, DirectCast(modifiedIdentifier, VisualBasicSyntaxNode)), diagBag) End If End If ' Check for array modifier on the identifier and array type. VB doesn't allow this combination. If IsArrayType(modifiedIdentifier) Then If asClauseSyntaxOpt IsNot Nothing Then If asClauseSyntaxOpt.Type.Kind = SyntaxKind.ArrayType Then ReportDiagnostic(diagBag, asClauseSyntaxOpt.Type, ERRID.ERR_CantSpecifyArraysOnBoth) ElseIf asClauseSyntaxOpt.Type.Kind = SyntaxKind.NullableType Then ' ReportDiagnostic(diagBag, asClauseSyntaxOpt, ERRID.ERR_CantSpecifyArrayAndNullableOnBoth) End If ElseIf (decoderContext And ModifiedIdentifierTypeDecoderContext.LambdaParameterType) = ModifiedIdentifierTypeDecoderContext.LambdaParameterType Then ' In lambda parameters's we don't allow array specifiers without the type since ' inference can become ambiguous, see bug dd:80897 ReportDiagnostic(diagBag, modifiedIdentifier, ERRID.ERR_CantSpecifyParamsOnLambdaParamNoType) End If End If Return ApplyArrayRankSpecifiersAndBoundsToType(baseType, modifiedIdentifier.ArrayRankSpecifiers, modifiedIdentifier.ArrayBounds, diagBag) End Function ''' <summary> ''' Given a modified identifier and a type syntax, return the actual type to use. Applies the type character ''' and type modifiers to the given type. ''' </summary> ''' <param name="modifiedIdentifier">The modified identifier.</param> ''' <param name="asClauseOpt"> As clause syntax. Can be nothing if no type was supplied.</param> ''' <param name="getRequireTypeDiagnosticInfoFunc">Delegate to get diagnostic info to generate if a required type is missing (Option Strict On/Custom) </param> ''' <param name="asClauseType">The type of the AsClauseOpt before applying any modifiers</param> ''' <returns>The type, as modified by the type character, type modifiers. Uses Object as default if needed.</returns> Public Function DecodeModifiedIdentifierType(modifiedIdentifier As ModifiedIdentifierSyntax, asClauseOpt As AsClauseSyntax, initializerSyntaxOpt As EqualsValueSyntax, getRequireTypeDiagnosticInfoFunc As Func(Of DiagnosticInfo), <Out()> ByRef asClauseType As TypeSymbol, diagBag As BindingDiagnosticBag, Optional decoderContext As ModifiedIdentifierTypeDecoderContext = Nothing ) As TypeSymbol If asClauseOpt IsNot Nothing Then ' NOTE: This method is NOT supposed to be called for 'As New With {...}' ' expression, if it is it should be revised to return bound node Debug.Assert(asClauseOpt.Kind <> SyntaxKind.AsNewClause OrElse DirectCast(asClauseOpt, AsNewClauseSyntax).NewExpression.Kind <> SyntaxKind.AnonymousObjectCreationExpression) asClauseType = BindTypeSyntax(asClauseOpt.Type, diagBag) Else asClauseType = Nothing End If Return DecodeModifiedIdentifierType(modifiedIdentifier, asClauseType, asClauseOpt, initializerSyntaxOpt, getRequireTypeDiagnosticInfoFunc, diagBag, decoderContext) End Function ''' <summary> ''' Given a modified identifier and a type syntax, return the actual type to use. Applies the type character ''' and type modifiers to the given type. ''' </summary> ''' <param name="modifiedIdentifier">The modified identifier.</param> ''' <param name="asClauseOpt"> As clause syntax. Can be nothing if no type was supplied.</param> ''' <param name="getRequireTypeDiagnosticInfoFunc">Delegate to get diagnostic info to generate if a required type is missing (Option Strict On/Custom) </param> ''' <returns>The type, as modified by the type character, type modifiers. Uses Object as default if needed.</returns> Public Function DecodeModifiedIdentifierType(modifiedIdentifier As ModifiedIdentifierSyntax, asClauseOpt As AsClauseSyntax, initializerSyntaxOpt As EqualsValueSyntax, getRequireTypeDiagnosticInfoFunc As Func(Of DiagnosticInfo), diagBag As BindingDiagnosticBag, Optional decoderContext As ModifiedIdentifierTypeDecoderContext = Nothing ) As TypeSymbol Dim asClauseType As TypeSymbol = Nothing Return DecodeModifiedIdentifierType(modifiedIdentifier, asClauseOpt, initializerSyntaxOpt, getRequireTypeDiagnosticInfoFunc, asClauseType, diagBag, decoderContext) End Function ''' <summary> ''' Given a identifier and as clause syntax, return the actual type to use. Uses the type character or the type syntax. ''' </summary> ''' <param name="identifier">The identifier.</param> ''' <param name="asClauseOpt">Syntax for optional as clause. Can be nothing if no type was supplied.</param> ''' <param name="getRequireTypeDiagnosticInfoFunc">Delegate to get diagnostic info to generate if a required type is missing (Option Strict On/Custom) </param> ''' <returns>The type, either from the type character or the as clause. Uses Object as default if needed.</returns> ''' <remarks></remarks> Public Function DecodeIdentifierType(identifier As SyntaxToken, asClauseOpt As AsClauseSyntax, getRequireTypeDiagnosticInfoFunc As Func(Of DiagnosticInfo), ByRef asClauseType As TypeSymbol, diagBag As BindingDiagnosticBag) As TypeSymbol If asClauseOpt IsNot Nothing Then asClauseType = BindTypeSyntax(asClauseOpt.Type, diagBag) Else asClauseType = Nothing End If Return DecodeIdentifierType(identifier, asClauseType, getRequireTypeDiagnosticInfoFunc, diagBag) End Function ''' <summary> ''' Given a identifier and as clause syntax, return the actual type to use. Uses the type character or the type syntax. ''' </summary> ''' <param name="identifier">The identifier.</param> ''' <param name="asClauseOpt">Syntax for optional as clause. Can be nothing if no type was supplied.</param> ''' <param name="getRequireTypeDiagnosticInfoFunc">Delegate to get diagnostic info to generate if a required type is missing (Option Strict On/Custom) </param> ''' <returns>The type, either from the type character or the as clause. Uses Object as default if needed.</returns> ''' <remarks></remarks> Public Function DecodeIdentifierType(identifier As SyntaxToken, asClauseOpt As AsClauseSyntax, getRequireTypeDiagnosticInfoFunc As Func(Of DiagnosticInfo), diagBag As BindingDiagnosticBag) As TypeSymbol Dim asClauseType As TypeSymbol = Nothing Return DecodeIdentifierType(identifier, asClauseOpt, getRequireTypeDiagnosticInfoFunc, asClauseType, diagBag) End Function ''' <summary> ''' Given a identifier and a type, return the actual type to use. Uses the type character or the given type. ''' </summary> ''' <param name="identifier">The identifier.</param> ''' <param name="asClauseType">Bound type after the As. Can be nothing if no type was supplied.</param> ''' <param name="getRequireTypeDiagnosticInfoFunc">Delegate to get diagnostic info to generate if a required type is missing (Option Strict On/Custom) </param> ''' <returns>The type, either from the type character or the as clause type. Uses Object as default if needed.</returns> ''' <remarks></remarks> Public Function DecodeIdentifierType(identifier As SyntaxToken, asClauseType As TypeSymbol, getRequireTypeDiagnosticInfoFunc As Func(Of DiagnosticInfo), diagBag As BindingDiagnosticBag, Optional decoderContext As ModifiedIdentifierTypeDecoderContext = ModifiedIdentifierTypeDecoderContext.None ) As TypeSymbol Dim typeCharacterType As TypeSymbol = Nothing Dim typeCharacterString As String = Nothing Dim specialType As SpecialType = GetSpecialTypeForTypeCharacter(identifier.GetTypeCharacter(), typeCharacterString) If specialType <> Microsoft.CodeAnalysis.SpecialType.None Then typeCharacterType = GetSpecialType(specialType, identifier, diagBag) End If If asClauseType IsNot Nothing Then ' We have a special error for this situation with query range variables, it is reported ' by the query binding code. If typeCharacterType IsNot Nothing AndAlso (decoderContext And ModifiedIdentifierTypeDecoderContext.QueryRangeVariableType) = 0 Then ReportDiagnostic(diagBag, identifier, ERRID.ERR_TypeCharWithType1, typeCharacterString) End If Return asClauseType ElseIf typeCharacterType IsNot Nothing Then Return typeCharacterType Else If getRequireTypeDiagnosticInfoFunc IsNot Nothing Then ReportDiagnostic(diagBag, identifier, getRequireTypeDiagnosticInfoFunc()) End If ' default type is object. Return GetSpecialType(SpecialType.System_Object, identifier, diagBag) End If End Function Public Shared Function GetSpecialTypeForTypeCharacter(typeChar As TypeCharacter, ByRef typeCharacterString As String) As SpecialType Dim specialType As SpecialType = SpecialType.None Select Case typeChar Case TypeCharacter.Decimal specialType = SpecialType.System_Decimal typeCharacterString = "@" Case TypeCharacter.DecimalLiteral specialType = SpecialType.System_Decimal typeCharacterString = "D" Case TypeCharacter.Double specialType = SpecialType.System_Double typeCharacterString = "#" Case TypeCharacter.DoubleLiteral specialType = SpecialType.System_Double typeCharacterString = "R" Case TypeCharacter.Integer specialType = SpecialType.System_Int32 typeCharacterString = "%" Case TypeCharacter.IntegerLiteral specialType = SpecialType.System_Int32 typeCharacterString = "I" Case TypeCharacter.Long specialType = SpecialType.System_Int64 typeCharacterString = "&" Case TypeCharacter.LongLiteral specialType = SpecialType.System_Int64 typeCharacterString = "L" Case TypeCharacter.ShortLiteral specialType = SpecialType.System_Int16 typeCharacterString = "S" Case TypeCharacter.Single specialType = SpecialType.System_Single typeCharacterString = "!" Case TypeCharacter.SingleLiteral specialType = SpecialType.System_Single typeCharacterString = "F" Case TypeCharacter.String specialType = SpecialType.System_String typeCharacterString = "$" Case TypeCharacter.UIntegerLiteral specialType = SpecialType.System_UInt32 typeCharacterString = "UI" Case TypeCharacter.ULongLiteral specialType = SpecialType.System_UInt64 typeCharacterString = "UL" Case TypeCharacter.UShortLiteral specialType = SpecialType.System_UInt16 typeCharacterString = "US" Case TypeCharacter.None typeCharacterString = Nothing Case Else Throw ExceptionUtilities.UnexpectedValue(typeChar) End Select Return specialType End Function Public Shared Function ExtractTypeCharacter(node As SyntaxNode) As TypeCharacter Dim result As TypeCharacter = TypeCharacter.None If node IsNot Nothing Then Select Case node.Kind Case SyntaxKind.IdentifierName result = DirectCast(node, IdentifierNameSyntax).Identifier.GetTypeCharacter() Case SyntaxKind.GenericName result = DirectCast(node, GenericNameSyntax).Identifier.GetTypeCharacter() Case SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.DictionaryAccessExpression result = ExtractTypeCharacter(DirectCast(node, MemberAccessExpressionSyntax).Name) End Select End If Return result End Function ''' <summary> ''' Decode an option "On" or "Off" values into true or false. Not specified is considered true. ''' </summary> Public Shared Function DecodeOnOff(keywordSyntax As SyntaxToken) As Boolean If keywordSyntax.Node Is Nothing Then Return True Else Select Case keywordSyntax.Kind Case SyntaxKind.OnKeyword Return True Case SyntaxKind.OffKeyword Return False Case Else Throw ExceptionUtilities.UnexpectedValue(keywordSyntax.Kind) End Select End If End Function ''' <summary> ''' Decode an option "Text" or "Binary" value into true or false. The syntax is not optional. ''' </summary> Public Shared Function DecodeTextBinary(keywordSyntax As SyntaxToken) As Boolean? If keywordSyntax.Node Is Nothing Then Return Nothing ' Must be a syntax error, an error is reported elsewhere End If Select Case keywordSyntax.Kind Case SyntaxKind.TextKeyword Return True Case SyntaxKind.BinaryKeyword Return False Case Else Throw ExceptionUtilities.UnexpectedValue(keywordSyntax.Kind) End Select End Function ''' <summary> ''' Decode a parameter list from a delegate declaration into a list of parameter symbols. ''' </summary> ''' <param name="container">Containing method declaration.</param> ''' <param name="syntaxOpt">Optional parameter list syntax</param> Public Function DecodeParameterListOfDelegateDeclaration( container As Symbol, syntaxOpt As ParameterListSyntax, diagBag As BindingDiagnosticBag ) As ImmutableArray(Of ParameterSymbol) If syntaxOpt Is Nothing Then Return ImmutableArray(Of ParameterSymbol).Empty End If Dim parametersSyntax = syntaxOpt.Parameters Dim params = ArrayBuilder(Of ParameterSymbol).GetInstance(parametersSyntax.Count) Dim result As ImmutableArray(Of ParameterSymbol) DecodeParameterList( container, False, SourceMemberFlags.None, parametersSyntax, params, s_checkDelegateParameterModifierCallback, diagBag) ' no checks for the parameters: ' Section 9.2.5, "Method Parameters" from the VB Language Reference mentions that duplicate parameter names are ' allowed but discouraged for delegates and extern methods ' Dev10: Function delegates are allowed to have one or more parameters called Invoke result = params.ToImmutable params.Free() Return result End Function ''' <summary> ''' Decode a parameter list into a list of parameter symbols. ''' </summary> ''' <param name="container">Containing method declaration.</param> ''' <param name="isFromLambda">Parameter is for a lambda expression rather than a regular method.</param> ''' <param name="syntaxOpt">Optional parameter list syntax</param> ''' <remarks>DO NOT call this to get the parameters of a delegate declaration (<see>DecodeParameterListOfDelegateDeclaration</see>).</remarks> Public Function DecodeParameterList(container As Symbol, isFromLambda As Boolean, modifiers As SourceMemberFlags, syntaxOpt As ParameterListSyntax, diagBag As BindingDiagnosticBag) As ImmutableArray(Of ParameterSymbol) Debug.Assert(Not (container.Kind = SymbolKind.Method AndAlso DirectCast(container, MethodSymbol).MethodKind = MethodKind.DelegateInvoke)) If syntaxOpt Is Nothing Then Return ImmutableArray(Of ParameterSymbol).Empty End If Dim params = ArrayBuilder(Of ParameterSymbol).GetInstance(syntaxOpt.Parameters.Count) Dim result As ImmutableArray(Of ParameterSymbol) Dim methodSymbol = TryCast(container, MethodSymbol) Dim modifierValidator As CheckParameterModifierDelegate = Nothing If methodSymbol IsNot Nothing AndAlso methodSymbol.IsUserDefinedOperator() Then modifierValidator = s_checkOperatorParameterModifierCallback End If DecodeParameterList( container, isFromLambda, modifiers, syntaxOpt.Parameters, params, modifierValidator, diagBag) Dim typeParams As ImmutableArray(Of TypeParameterSymbol) = If(methodSymbol IsNot Nothing AndAlso Not isFromLambda, methodSymbol.TypeParameters, ImmutableArray(Of TypeParameterSymbol).Empty) For i = 0 To params.Count - 1 Dim paramSyntax = syntaxOpt.Parameters(i) Dim param = params(i) If methodSymbol IsNot Nothing Then If Not methodSymbol.IsSub AndAlso Not methodSymbol.IsUserDefinedOperator() Then ' "Parameter cannot have the same name as its defining function." CheckReservedParameterName(container.Name, paramSyntax, ERRID.ERR_ParamNameFunctionNameCollision, diagBag) End If ' Section 9.2.5, "Method Parameters" from the VB Language Reference mentions that duplicate parameter names ' are allowed but discouraged for delegates and extern methods If Not methodSymbol.MethodKind = MethodKind.DeclareMethod Then CheckParameterNameNotDuplicate(params, i, paramSyntax, param, diagBag) End If End If Dim name = param.Name For Each tp In typeParams If CaseInsensitiveComparison.Equals(tp.Name, name) Then ' "'{0}' is already declared as a type parameter of this method." ReportDiagnostic(diagBag, paramSyntax.Identifier, ERRID.ERR_NameSameAsMethodTypeParam1, name) Exit For End If Next Next result = params.ToImmutable params.Free() Return result End Function Private Shared ReadOnly s_checkOperatorParameterModifierCallback As CheckParameterModifierDelegate = AddressOf CheckOperatorParameterModifier Private Shared Function CheckOperatorParameterModifier(container As Symbol, token As SyntaxToken, flag As SourceParameterFlags, diagnostics As BindingDiagnosticBag) As SourceParameterFlags If (flag And SourceParameterFlags.ByRef) <> 0 Then diagnostics.Add(ERRID.ERR_ByRefIllegal1, token.GetLocation(), container.GetKindText()) flag = flag And (Not SourceParameterFlags.ByRef) End If If (flag And SourceParameterFlags.ParamArray) <> 0 Then diagnostics.Add(ERRID.ERR_ParamArrayIllegal1, token.GetLocation(), container.GetKindText()) flag = flag And (Not SourceParameterFlags.ParamArray) End If If (flag And SourceParameterFlags.Optional) <> 0 Then diagnostics.Add(ERRID.ERR_OptionalIllegal1, token.GetLocation(), container.GetKindText()) flag = flag And (Not SourceParameterFlags.Optional) End If Return flag End Function ''' <summary> ''' Decode a parameter list into a list of parameter symbols. ''' </summary> ''' <param name="container">Containing property declaration.</param> ''' <param name="syntaxOpt">Optional parameter list syntax</param> Public Function DecodePropertyParameterList(container As PropertySymbol, syntaxOpt As ParameterListSyntax, diagBag As BindingDiagnosticBag) As ImmutableArray(Of ParameterSymbol) If syntaxOpt Is Nothing Then Return ImmutableArray(Of ParameterSymbol).Empty End If Dim params = ArrayBuilder(Of ParameterSymbol).GetInstance(syntaxOpt.Parameters.Count) Dim result As ImmutableArray(Of ParameterSymbol) DecodeParameterList( container, False, SourceMemberFlags.None, syntaxOpt.Parameters, params, s_checkPropertyParameterModifierCallback, diagBag) For i = 0 To params.Count - 1 Dim paramSyntax = syntaxOpt.Parameters(i) Dim param = params(i) ' "Property parameters cannot have the name 'Value'." If CheckReservedParameterName(StringConstants.ValueParameterName, paramSyntax, ERRID.ERR_PropertySetParamCollisionWithValue, diagBag) Then ' "Parameter cannot have the same name as its defining function." CheckReservedParameterName(container.Name, paramSyntax, ERRID.ERR_ParamNameFunctionNameCollision, diagBag) End If CheckParameterNameNotDuplicate(params, i, paramSyntax, param, diagBag) Next result = params.ToImmutable params.Free() Return result End Function Private Shared ReadOnly s_checkPropertyParameterModifierCallback As CheckParameterModifierDelegate = AddressOf CheckPropertyParameterModifier Private Shared Function CheckPropertyParameterModifier(container As Symbol, token As SyntaxToken, flag As SourceParameterFlags, diagnostics As BindingDiagnosticBag) As SourceParameterFlags If flag = SourceParameterFlags.ByRef Then Dim location = token.GetLocation() diagnostics.Add(ERRID.ERR_ByRefIllegal1, location, container.GetKindText(), token.ToString()) Return flag And (Not SourceParameterFlags.ByRef) End If Return flag End Function Private Shared Function CheckReservedParameterName(reservedName As String, syntax As ParameterSyntax, errorId As ERRID, diagnostics As BindingDiagnosticBag) As Boolean Dim identifier = syntax.Identifier Dim name = identifier.Identifier.ValueText If IdentifierComparison.Equals(reservedName, name) Then Dim location = identifier.GetLocation() diagnostics.Add(errorId, location) Return False End If Return True End Function ' TODO: Caller is O(n^2). Friend Shared Sub CheckParameterNameNotDuplicate( params As ArrayBuilder(Of ParameterSymbol), nParams As Integer, syntax As ParameterSyntax, parameter As ParameterSymbol, diagnostics As BindingDiagnosticBag) Dim name = parameter.Name For i = 0 To nParams - 1 If IdentifierComparison.Equals(params(i).Name, name) Then ' "Parameter already declared with name '{0}'." ReportDiagnostic(diagnostics, syntax.Identifier, ERRID.ERR_DuplicateParamName1, name) Return End If Next End Sub Friend Delegate Function CheckParameterModifierDelegate(container As Symbol, token As SyntaxToken, flag As SourceParameterFlags, diagnostics As BindingDiagnosticBag) As SourceParameterFlags Public Sub DecodeParameterList(container As Symbol, isFromLambda As Boolean, modifiers As SourceMemberFlags, syntax As SeparatedSyntaxList(Of ParameterSyntax), params As ArrayBuilder(Of ParameterSymbol), checkModifier As CheckParameterModifierDelegate, diagBag As BindingDiagnosticBag) Dim count As Integer = syntax.Count Dim ordinal = params.Count Dim paramHasImplicitType = False, paramHasExplicitType = False Dim flagsOfPreviousParameters As SourceParameterFlags = Nothing Dim reportedError = False For i = 0 To count - 1 Dim paramSyntax = syntax(i) Dim name = paramSyntax.Identifier.Identifier.ValueText Dim flags As SourceParameterFlags = Nothing flags = DecodeParameterModifiers(container, paramSyntax.Modifiers, checkModifier, diagBag) If (flagsOfPreviousParameters And SourceParameterFlags.Optional) = SourceParameterFlags.Optional Then If (flags And SourceParameterFlags.ParamArray) = SourceParameterFlags.ParamArray AndAlso Not reportedError Then ' If one of the previous parameters is optional then report an error if paramarray is specified. ReportDiagnostic(diagBag, paramSyntax.Identifier.Identifier, ERRID.ERR_ParamArrayWithOptArgs) reportedError = True ElseIf (flags And SourceParameterFlags.Optional) <> SourceParameterFlags.Optional AndAlso Not reportedError Then ' If one of the previous parameters is optional then report an error if this one isn't optional. ReportDiagnostic(diagBag, paramSyntax.Identifier.Identifier, ERRID.ERR_ExpectedOptional) reportedError = True End If End If If (flagsOfPreviousParameters And SourceParameterFlags.ParamArray) <> 0 AndAlso Not reportedError Then ReportDiagnostic(diagBag, paramSyntax, ERRID.ERR_ParamArrayMustBeLast) reportedError = True End If Dim newParam As ParameterSymbol If isFromLambda Then newParam = UnboundLambdaParameterSymbol.CreateFromSyntax(paramSyntax, name, flags, ordinal, Me, diagBag) Else newParam = SourceComplexParameterSymbol.CreateFromSyntax(container, paramSyntax, name, flags, ordinal, Me, checkModifier, diagBag) End If ordinal += 1 If newParam.IsByRef AndAlso (modifiers And SourceMemberFlags.Async) = SourceMemberFlags.Async Then ReportDiagnostic(diagBag, paramSyntax, ERRID.ERR_BadAsyncByRefParam) ElseIf newParam.IsByRef AndAlso (modifiers And SourceMemberFlags.Iterator) = SourceMemberFlags.Iterator Then ReportDiagnostic(diagBag, paramSyntax, ERRID.ERR_BadIteratorByRefParam) Else Dim paramType As TypeSymbol = newParam.Type If paramType IsNot Nothing Then If paramType.IsArrayType() Then Dim restrictedType As TypeSymbol = Nothing If paramType.IsRestrictedArrayType(restrictedType) Then ReportDiagnostic(diagBag, paramSyntax.AsClause.Type, ERRID.ERR_RestrictedType1, restrictedType) End If ElseIf newParam.IsByRef Then If paramType.IsRestrictedType Then ReportDiagnostic(diagBag, paramSyntax.AsClause.Type, ERRID.ERR_RestrictedType1, paramType) End If ElseIf (modifiers And (SourceMemberFlags.Async Or SourceMemberFlags.Iterator)) <> 0 Then If paramType.IsRestrictedType Then ReportDiagnostic(diagBag, paramSyntax.AsClause.Type, ERRID.ERR_RestrictedResumableType1, paramType) End If End If End If End If If Not isFromLambda AndAlso Not newParam.Type.IsErrorType() Then AccessCheck.VerifyAccessExposureForParameterType(container, newParam.Name, If(paramSyntax.AsClause IsNot Nothing, paramSyntax.AsClause.Type, DirectCast(paramSyntax, VisualBasicSyntaxNode)), newParam.Type, diagBag) End If params.Add(newParam) If HasDefaultType(paramSyntax.Identifier, paramSyntax.AsClause) Then paramHasImplicitType = True Else paramHasExplicitType = True End If flagsOfPreviousParameters = flagsOfPreviousParameters Or flags Next ' Special rule: if any parameters have implicit type, all must have implicit type. ' Report the error on each parameter with implicit type. If paramHasImplicitType AndAlso paramHasExplicitType Then For i = 0 To count - 1 Dim paramSyntax = syntax(i) If HasDefaultType(paramSyntax.Identifier, paramSyntax.AsClause) Then ReportDiagnostic(diagBag, paramSyntax.Identifier, ERRID.ERR_ParamTypingInconsistency) End If Next End If End Sub ' An array consisting of just the NotInheritable keyword. Private Shared ReadOnly s_notInheritableKeyword As SyntaxKind() = {SyntaxKind.NotInheritableKeyword} ''' <summary> ''' Modifier validation code shared between properties and methods. ''' </summary> Public Function ValidateSharedPropertyAndMethodModifiers(modifierList As SyntaxTokenList, memberModifiers As MemberModifiers, isProperty As Boolean, container As SourceMemberContainerTypeSymbol, diagBag As DiagnosticBag) As MemberModifiers Dim flags = memberModifiers.FoundFlags If (flags And SourceMemberFlags.Shared) <> 0 AndAlso (flags And SourceMemberFlags.InvalidIfShared) <> 0 Then ReportModifierError(modifierList, If(isProperty, ERRID.ERR_BadFlagsOnSharedProperty1, ERRID.ERR_BadFlagsOnSharedMeth1), diagBag, InvalidModifiersIfShared) flags = flags And Not SourceMemberFlags.InvalidIfShared memberModifiers = New MemberModifiers(flags, memberModifiers.ComputedFlags) End If Select Case container.TypeKind Case TypeKind.Module ' Don't allow overloads in module If (flags And SourceMemberFlags.Overloads) <> 0 Then ReportModifierError(modifierList, ERRID.ERR_OverloadsModifierInModule, diagBag, SyntaxKind.OverloadsKeyword) flags = flags And Not SourceMemberFlags.Overloads End If ' Members in module are implicitly Shared, and cannot be explicitly Shared. If (flags And SourceMemberFlags.InvalidInModule) <> 0 Then ReportModifierError(modifierList, If(isProperty, ERRID.ERR_BadFlagsOnStdModuleProperty1, ERRID.ERR_ModuleCantUseMethodSpecifier1), diagBag, InvalidModifiersInModule) If (flags And SourceMemberFlags.Protected) <> 0 Then flags = flags And Not SourceMemberFlags.Friend ' remove "Friend" if removing "Protected" End If flags = flags And Not SourceMemberFlags.InvalidInModule End If memberModifiers = New MemberModifiers(flags, memberModifiers.ComputedFlags Or SourceMemberFlags.Shared) Case TypeKind.Interface If (flags And SourceMemberFlags.InvalidInInterface) <> 0 Then ReportModifierError(modifierList, If(isProperty, ERRID.ERR_BadInterfacePropertyFlags1, ERRID.ERR_BadInterfaceMethodFlags1), diagBag, InvalidModifiersInInterface) flags = flags And Not SourceMemberFlags.InvalidInInterface End If ' Interface members are always public and always implicitly MustOverride. memberModifiers = New MemberModifiers(flags, memberModifiers.ComputedFlags Or SourceMemberFlags.MustOverride) Case TypeKind.Structure If (flags And SourceMemberFlags.Protected) <> 0 AndAlso (flags And SourceMemberFlags.Overrides) = 0 Then ReportModifierError(modifierList, If(isProperty, ERRID.ERR_StructCantUseVarSpecifier1, ERRID.ERR_StructureCantUseProtected), diagBag, SyntaxKind.ProtectedKeyword) flags = flags And Not SourceMemberFlags.Protected memberModifiers = New MemberModifiers(flags, (memberModifiers.ComputedFlags And Not SourceMemberFlags.AccessibilityMask) Or SourceMemberFlags.AccessibilityPrivate) End If If (flags And SourceMemberFlags.InvalidInNotInheritableClass) <> 0 Then ReportModifierError(modifierList, ERRID.ERR_StructCantUseVarSpecifier1, diagBag, SyntaxKind.OverridableKeyword, SyntaxKind.NotOverridableKeyword, SyntaxKind.MustOverrideKeyword) flags = flags And Not SourceMemberFlags.InvalidInNotInheritableClass End If End Select ' Don't allow Overridable, etc. on NotInheritable. If container.IsNotInheritable Then If (flags And SourceMemberFlags.InvalidInNotInheritableClass) <> 0 Then ' Somewhat strangely, the old VB compiler has different behavior depending on whether the containing type DECLARATION ' has NotInheritable, vs. any partial has NotInheritable (although they are semantically the same). If the containing declaration ' does not have NotInheritable, then only MustOverride has an error reported for it, and the error has a different code. Dim containingTypeBLock = GetContainingTypeBlock(modifierList.First()) If containingTypeBLock IsNot Nothing AndAlso FindFirstKeyword(containingTypeBLock.BlockStatement.Modifiers, s_notInheritableKeyword).Kind = SyntaxKind.None Then ' Containing type block doesn't have a NotInheritable modifier on it. Must be from other partial declaration. If (flags And SourceMemberFlags.InvalidInNotInheritableOtherPartialClass) <> 0 Then ReportModifierError(modifierList, ERRID.ERR_MustOverOnNotInheritPartClsMem1, diagBag, InvalidModifiersInNotInheritableOtherPartialClass) flags = flags And Not SourceMemberFlags.InvalidInNotInheritableOtherPartialClass End If Else ReportModifierError(modifierList, ERRID.ERR_BadFlagsInNotInheritableClass1, diagBag, InvalidModifiersInNotInheritableClass) flags = flags And Not SourceMemberFlags.InvalidInNotInheritableClass End If memberModifiers = New MemberModifiers(flags, memberModifiers.ComputedFlags) End If End If Return memberModifiers End Function Public Function ValidateEventModifiers(modifierList As SyntaxTokenList, memberModifiers As MemberModifiers, container As SourceMemberContainerTypeSymbol, diagBag As DiagnosticBag) As MemberModifiers Dim flags = memberModifiers.FoundFlags Select Case container.TypeKind Case TypeKind.Module ' Members in module are implicitly Shared, and cannot be explicitly Shared. If (flags And SourceMemberFlags.InvalidInModule) <> 0 Then ReportModifierError(modifierList, ERRID.ERR_ModuleCantUseEventSpecifier1, diagBag, InvalidModifiersInModule) If (flags And SourceMemberFlags.Protected) <> 0 Then flags = flags And Not SourceMemberFlags.Friend ' remove "Friend" if removing "Protected" End If flags = flags And Not SourceMemberFlags.InvalidInModule End If memberModifiers = New MemberModifiers(flags, memberModifiers.ComputedFlags Or SourceMemberFlags.Shared) Case TypeKind.Interface If (flags And SourceMemberFlags.InvalidInInterface) <> 0 Then ReportModifierError(modifierList, ERRID.ERR_InterfaceCantUseEventSpecifier1, diagBag, InvalidModifiersInInterface) flags = flags And Not SourceMemberFlags.InvalidInInterface End If ' Interface members are always public and always implicitly MustOverride. memberModifiers = New MemberModifiers(flags, memberModifiers.ComputedFlags Or SourceMemberFlags.MustOverride) Case TypeKind.Structure If (flags And SourceMemberFlags.Protected) <> 0 Then ReportModifierError(modifierList, ERRID.ERR_StructureCantUseProtected, diagBag, SyntaxKind.ProtectedKeyword) flags = flags And Not SourceMemberFlags.Protected memberModifiers = New MemberModifiers(flags, (memberModifiers.ComputedFlags And Not SourceMemberFlags.AccessibilityMask) Or SourceMemberFlags.AccessibilityPrivate) End If End Select Return memberModifiers End Function ' Get the containing type block containing a modifier token on a declared member, or Nothing if no such type block. Private Shared Function GetContainingTypeBlock(modifierToken As SyntaxToken) As TypeBlockSyntax Dim containingSyntax = modifierToken.Parent If TypeOf containingSyntax.Parent Is MethodBlockBaseSyntax OrElse TypeOf containingSyntax.Parent Is PropertyBlockSyntax Then containingSyntax = containingSyntax.Parent End If Return TryCast(containingSyntax.Parent, TypeBlockSyntax) End Function Public Enum ConstantContext [Default] ParameterDefaultValue End Enum ''' <summary> ''' This function checks if the given expression is a constant from a language point of view and returns ''' constant value if it is. This is different from the fact that the bound node has a constant value. ''' This method also adds the required diagnostics for non const values. ''' </summary> ''' <param name="boundExpression">The bound expression.</param> ''' <param name="diagnostics">The diagnostics.</param> ''' <returns>ConstantValue if the bound expression is compile time constant and can be used ''' for const field/local initializations or enum member initializations. Nothing if not</returns> Public Function GetExpressionConstantValueIfAny(boundExpression As BoundExpression, diagnostics As BindingDiagnosticBag, context As ConstantContext) As ConstantValue Dim nonConstantDetected As Boolean = False Do If boundExpression.Kind = BoundKind.Local Then Dim local = DirectCast(boundExpression, BoundLocal).LocalSymbol If Not local.IsConst Then ReportDiagnostic(diagnostics, boundExpression.Syntax, ERRID.ERR_RequiredConstExpr) Return Nothing End If Return If(nonConstantDetected, Nothing, local.GetConstantValue(Me)) End If ' Check that the expression is constant. If boundExpression.ConstantValueOpt IsNot Nothing Then ' if no non constant node was found this if node is constant. Return If(nonConstantDetected, Nothing, boundExpression.ConstantValueOpt) Else Select Case boundExpression.Kind Case BoundKind.DirectCast Dim conv = DirectCast(boundExpression, BoundDirectCast) Dim result = CheckConversionForConstantExpression(conv, conv.Operand, diagnostics, context) Return If(nonConstantDetected, Nothing, result) Case BoundKind.TryCast Dim conv = DirectCast(boundExpression, BoundTryCast) Dim result = CheckConversionForConstantExpression(conv, conv.Operand, diagnostics, context) Return If(nonConstantDetected, Nothing, result) Case BoundKind.Conversion Dim conv = DirectCast(boundExpression, BoundConversion) Dim result = CheckConversionForConstantExpression(conv, conv.Operand, diagnostics, context) Return If(nonConstantDetected, Nothing, result) Case BoundKind.BinaryOperator ' If we ever got to a binary operator it means there is no constant value, ' but we want to keep the analysis going to properly report errors Dim binaryOperator = DirectCast(boundExpression, BoundBinaryOperator) ' the right side is expected to be shorter for binary operations, so we use ' recursion for this side. GetExpressionConstantValueIfAny(binaryOperator.Right, diagnostics, context) nonConstantDetected = True boundExpression = binaryOperator.Left Case BoundKind.UnaryOperator boundExpression = DirectCast(boundExpression, BoundUnaryOperator).Operand Case BoundKind.Parenthesized boundExpression = DirectCast(boundExpression, BoundParenthesized).Expression Case BoundKind.BadExpression Return Nothing Case Else ReportDiagnostic(diagnostics, boundExpression.Syntax, ERRID.ERR_RequiredConstExpr) Return Nothing End Select End If Loop Return Nothing End Function Private Shared Function IsNothingLiteralAllowedForAType(type As TypeSymbol) As Boolean If type.IsReferenceType Then Return True End If If type.IsEnumType Then Return True End If Select Case type.SpecialType Case SpecialType.System_Boolean, SpecialType.System_Byte, SpecialType.System_SByte, SpecialType.System_Int16, SpecialType.System_UInt16, SpecialType.System_Int32, SpecialType.System_UInt32, SpecialType.System_Int64, SpecialType.System_UInt64, SpecialType.System_Single, SpecialType.System_Double, SpecialType.System_Char Return True End Select Return False End Function Private Function CheckConversionForConstantExpression(conv As BoundExpression, operand As BoundExpression, diagnostics As BindingDiagnosticBag, context As ConstantContext) As ConstantValue If conv.HasErrors Then Return Nothing End If Dim conversionType As TypeSymbol = conv.Type Dim operandType As TypeSymbol = operand.Type ' First, special handling for the case when operand is a Nothing Literal If operand.IsNothingLiteral Then If context = ConstantContext.Default Then ' In default context, Nothing literal can only be converted to either a reference type ' or an intrinsic value type allowing constant values, like int32, etc... If Not IsNothingLiteralAllowedForAType(conversionType) Then ReportDiagnostic(diagnostics, operand.Syntax, ERRID.ERR_RequiredConstConversion2, If(operandType, GetSpecialType(SpecialType.System_Object, operand.Syntax, diagnostics)), conversionType) Return Nothing End If Else ' In ParameterDefaultValue constant context 'Nothing' literal can be ' converted to any type meaning the type's default value; Debug.Assert(context = ConstantContext.ParameterDefaultValue) End If Return operand.ConstantValueOpt End If ' Guess the constant value of the operand Dim nestedConstValue As ConstantValue = GetExpressionConstantValueIfAny(operand, diagnostics, context) If nestedConstValue Is Nothing Then ' Error should already be generated Return Nothing End If Debug.Assert(conversionType IsNot Nothing) Debug.Assert(operandType IsNot Nothing) If conversionType.IsObjectType Then ' Nothing constants of reference type can always be converted to System.Object If operandType.IsReferenceType AndAlso nestedConstValue.IsNothing Then Return nestedConstValue End If ' In ParameterDefaultValue context we also allow constant of types DateTime, Decimal ' and others mentioned as supported by IsNothingLiteralAllowedForAType() to be converted ' to System.Object type; these constants will be emitted as constant values for appropriate ' parameters and when used converted to target type if needed If context = ConstantContext.ParameterDefaultValue AndAlso (IsNothingLiteralAllowedForAType(operandType) OrElse operandType.IsDateTimeType OrElse operandType.IsDecimalType) Then Return nestedConstValue End If ReportDiagnostic(diagnostics, operand.Syntax, ERRID.ERR_RequiredConstConversion2, operandType, conversionType) Return Nothing End If If Not nestedConstValue.IsNothing Then ' Conversion of a non-nothing constant value to anything but System.Object is bad ' Note that all valid intrinsic conversions should have been folded and never reach this point ' In ParameterDefaultValue we also allow conversion of T --> S? If context = ConstantContext.ParameterDefaultValue AndAlso conversionType.IsNullableType Then If IsSameTypeIgnoringAll(conversionType.GetNullableUnderlyingType, operandType) Then ' A trivial case: T --> T? Return nestedConstValue Else ' Let's convert to the underlying type of the Nullable. ' All diagnostics about this conversion have already been reported, so we can treat it as an explicit conversion and ignore any errors/warnings. Dim conversionToUnderlying As BoundExpression = ApplyConversion(operand.Syntax, conversionType.GetNullableUnderlyingType(), operand, isExplicit:=True, diagnostics:=BindingDiagnosticBag.Discarded) nestedConstValue = conversionToUnderlying.ConstantValueOpt If nestedConstValue IsNot Nothing Then Return nestedConstValue End If End If End If ReportDiagnostic(diagnostics, operand.Syntax, ERRID.ERR_RequiredConstConversion2, operandType, conversionType) Return Nothing End If ' We have a 'Nothing' constant value which was converted to some ' type by nested conversion(s) and now has type of the argument ' No actual conversion is done If IsSameTypeIgnoringAll(operandType, conversionType) Then Return nestedConstValue End If ' It is OK to convert Nothing literal of one reference type to another ' reference type or (only in default parameter value context) Nothing ' literal of reference type to a value type, ' if the conversion is not correct, errors should have been reported by now If operandType.IsReferenceType AndAlso (conversionType.IsReferenceType OrElse context = ConstantContext.ParameterDefaultValue) Then Return nestedConstValue End If ' In ParameterDefaultValue we also allow conversion of 'Nothing' constants to nullable If context = ConstantContext.ParameterDefaultValue Then If conversionType.IsNullableType Then Return nestedConstValue End If End If ReportDiagnostic(diagnostics, operand.Syntax, ERRID.ERR_RequiredConstConversion2, operandType, conversionType) Return Nothing End Function ''' <summary>isWinMd says whether to mangle the name for winmdobj output. See the param tag for details.</summary> ''' <param name="isWinMd">isWinMd is only necessary for set properties, so any MethodKind which is definitely not ''' a set property can safely set this value to False.</param> Friend Shared Function GetAccessorName(name As String, kind As MethodKind, isWinMd As Boolean) As String Dim prefix As String Select Case kind Case MethodKind.PropertyGet prefix = StringConstants.PropertyGetPrefix Case MethodKind.PropertySet If isWinMd Then prefix = StringConstants.WinMdPropertySetPrefix Else prefix = StringConstants.PropertySetPrefix End If Case MethodKind.EventAdd prefix = StringConstants.EventAddPrefix Case MethodKind.EventRemove prefix = StringConstants.EventRemovePrefix Case MethodKind.EventRaise prefix = StringConstants.EventRaisePrefix Case Else Throw ExceptionUtilities.UnexpectedValue(kind) End Select Return prefix & name End Function End Class ''' <summary> ''' Holds information about a member in a compact form. Used for all non-type members for simplicity ''' </summary> ''' <remarks></remarks> <Flags()> Friend Enum SourceMemberFlags None = 0 ' These are the actual accessibility level ' Bits 0,1,2 AccessibilityPrivate = CUShort(Accessibility.Private) AccessibilityProtected = CUShort(Accessibility.Protected) AccessibilityFriend = CUShort(Accessibility.Friend) AccessibilityProtectedFriend = CUShort(Accessibility.ProtectedOrFriend) AccessibilityPrivateProtected = CUShort(Accessibility.ProtectedAndFriend) AccessibilityPublic = CUShort(Accessibility.Public) AccessibilityMask = &H7 ' DeclarationModifierFlags ' Bits 3,4,5,...,27 [Private] = CUInt(DeclarationModifiers.Private) << DeclarationModifierFlagShift [Protected] = CUInt(DeclarationModifiers.Protected) << DeclarationModifierFlagShift [Friend] = CUInt(DeclarationModifiers.Friend) << DeclarationModifierFlagShift [Public] = CUInt(DeclarationModifiers.Public) << DeclarationModifierFlagShift AllAccessibilityModifiers = [Private] Or [Friend] Or [Protected] Or [Public] [Shared] = CUInt(DeclarationModifiers.Shared) << DeclarationModifierFlagShift [ReadOnly] = CUInt(DeclarationModifiers.ReadOnly) << DeclarationModifierFlagShift [WriteOnly] = CUInt(DeclarationModifiers.WriteOnly) << DeclarationModifierFlagShift AllWriteabilityModifiers = [ReadOnly] Or [WriteOnly] [Overrides] = CUInt(DeclarationModifiers.Overrides) << DeclarationModifierFlagShift [Overridable] = CUInt(DeclarationModifiers.Overridable) << DeclarationModifierFlagShift [MustOverride] = CUInt(DeclarationModifiers.MustOverride) << DeclarationModifierFlagShift [NotOverridable] = CUInt(DeclarationModifiers.NotOverridable) << DeclarationModifierFlagShift AllOverrideModifiers = [Overridable] Or [MustOverride] Or [NotOverridable] PrivateOverridableModifiers = [Overridable] Or [Private] PrivateMustOverrideModifiers = [MustOverride] Or [Private] PrivateNotOverridableModifiers = [NotOverridable] Or [Private] [Overloads] = CUInt(DeclarationModifiers.Overloads) << DeclarationModifierFlagShift [Shadows] = CUInt(DeclarationModifiers.Shadows) << DeclarationModifierFlagShift AllShadowingModifiers = [Overloads] Or [Shadows] ShadowsAndOverrides = [Overrides] Or [Shadows] [Default] = CUInt(DeclarationModifiers.Default) << DeclarationModifierFlagShift [WithEvents] = CUInt(DeclarationModifiers.WithEvents) << DeclarationModifierFlagShift [Widening] = CUInt(DeclarationModifiers.Widening) << DeclarationModifierFlagShift [Narrowing] = CUInt(DeclarationModifiers.Narrowing) << DeclarationModifierFlagShift AllConversionModifiers = [Widening] Or [Narrowing] ' These should be kept in sync with the corresponding arrays in InvalidModifiers below. InvalidInNotInheritableClass = [Overridable] Or [NotOverridable] Or [MustOverride] InvalidInNotInheritableOtherPartialClass = [MustOverride] ' invalid if containing declaration doesn't have NotInheritable, but other partial does. InvalidInModule = [Protected] Or [Shared] Or [Default] Or [MustOverride] Or [Overridable] Or [Shadows] Or [Overrides] Or [NotOverridable] InvalidInInterface = AllAccessibilityModifiers Or [Shared] Or [Overrides] Or AllOverrideModifiers Or [Dim] Or [Const] Or [Static] Or [WithEvents] Or AllConversionModifiers Or [Partial] Or [MustInherit] Or [NotInheritable] Or Async Or Iterator InvalidIfShared = [Overrides] Or AllOverrideModifiers Or [Default] InvalidIfDefault = [Private] [Partial] = CUInt(DeclarationModifiers.Partial) << DeclarationModifierFlagShift [MustInherit] = CUInt(DeclarationModifiers.MustInherit) << DeclarationModifierFlagShift [NotInheritable] = CUInt(DeclarationModifiers.NotInheritable) << DeclarationModifierFlagShift TypeInheritModifiers = [MustInherit] Or [NotInheritable] Async = CUInt(DeclarationModifiers.Async) << DeclarationModifierFlagShift Iterator = CUInt(DeclarationModifiers.Iterator) << DeclarationModifierFlagShift [Dim] = CUInt(DeclarationModifiers.Dim) << DeclarationModifierFlagShift [Const] = CUInt(DeclarationModifiers.Const) << DeclarationModifierFlagShift [Static] = CUInt(DeclarationModifiers.Static) << DeclarationModifierFlagShift DeclarationModifierFlagMask = &HFFFFFF8 DeclarationModifierFlagShift = 3 ' Bits 25 and above are used for different things depending on the member type. ' 25 - [Dim] ' 26 - [Const] ' 27 - [Static] ' Fields only: Indicates that this const field has an inferred type. InferredFieldType = 1 << 30 ' Fields and properties only: Indicates that this is the first field (or property representing a WithEvents field) of a particular type. ' In "Dim x, y, z As Integer, w As String, a, b as Decimal", set for "x", "w", and "a" FirstFieldDeclarationOfType = 1 << 31 ' Source Methods only: Indicates this method has a void return type / is a Sub. MethodIsSub = 1 << 25 ' Source methods only: Indicates that method syntax has "Handles" MethodHandlesEvents = 1 << 26 ' Method symbols only: Bits 27,28,29,30,31 MethodKindOrdinary = CUInt(MethodKind.Ordinary) << MethodKindShift MethodKindConstructor = CUInt(MethodKind.Constructor) << MethodKindShift MethodKindSharedConstructor = CUInt(MethodKind.SharedConstructor) << MethodKindShift MethodKindDelegateInvoke = CUInt(MethodKind.DelegateInvoke) << MethodKindShift MethodKindOperator = CUInt(MethodKind.UserDefinedOperator) << MethodKindShift MethodKindConversion = CUInt(MethodKind.Conversion) << MethodKindShift MethodKindPropertyGet = CUInt(MethodKind.PropertyGet) << MethodKindShift MethodKindPropertySet = CUInt(MethodKind.PropertySet) << MethodKindShift MethodKindEventAdd = CUInt(MethodKind.EventAdd) << MethodKindShift MethodKindEventRemove = CUInt(MethodKind.EventRemove) << MethodKindShift MethodKindEventRaise = CUInt(MethodKind.EventRaise) << MethodKindShift MethodKindDeclare = CUInt(MethodKind.DeclareMethod) << MethodKindShift MethodKindMask = &H1F MethodKindShift = 27 End Enum Friend Module SourceMemberFlagsExtensions <Extension> Friend Function ToMethodKind(flags As SourceMemberFlags) As MethodKind Return CType((flags >> SourceMemberFlags.MethodKindShift) And SourceMemberFlags.MethodKindMask, MethodKind) End Function End Module ' These should be kept in sync with the corresponding bit fields in SourceMemberFlags above. Friend Module InvalidModifiers Public InvalidModifiersInNotInheritableClass() As SyntaxKind = { SyntaxKind.OverridableKeyword, SyntaxKind.NotOverridableKeyword, SyntaxKind.MustOverrideKeyword } Public InvalidModifiersInNotInheritableOtherPartialClass() As SyntaxKind = { SyntaxKind.MustOverrideKeyword } Public InvalidModifiersInModule() As SyntaxKind = { SyntaxKind.SharedKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.DefaultKeyword, SyntaxKind.MustOverrideKeyword, SyntaxKind.OverridableKeyword, SyntaxKind.ShadowsKeyword, SyntaxKind.OverridesKeyword, SyntaxKind.NotOverridableKeyword } Public InvalidModifiersInInterface() As SyntaxKind = { SyntaxKind.PublicKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.FriendKeyword, SyntaxKind.StaticKeyword, SyntaxKind.SharedKeyword, SyntaxKind.MustInheritKeyword, SyntaxKind.NotInheritableKeyword, SyntaxKind.OverridesKeyword, SyntaxKind.PartialKeyword, SyntaxKind.NotOverridableKeyword, SyntaxKind.OverridableKeyword, SyntaxKind.MustOverrideKeyword, SyntaxKind.DimKeyword, SyntaxKind.ConstKeyword, SyntaxKind.WithEventsKeyword, SyntaxKind.WideningKeyword, SyntaxKind.NarrowingKeyword, SyntaxKind.CustomKeyword, SyntaxKind.AsyncKeyword, SyntaxKind.IteratorKeyword } Public InvalidModifiersIfShared() As SyntaxKind = { SyntaxKind.OverridesKeyword, SyntaxKind.OverridableKeyword, SyntaxKind.MustOverrideKeyword, SyntaxKind.NotOverridableKeyword, SyntaxKind.DefaultKeyword } Public InvalidModifiersIfDefault() As SyntaxKind = { SyntaxKind.PrivateKeyword } Public InvalidAsyncIterator() As SyntaxKind = { SyntaxKind.AsyncKeyword, SyntaxKind.IteratorKeyword } End Module Friend Structure MemberModifiers ''' <summary> ''' These are the flags that are found in the syntax. They must correspond to the modifiers list. ''' </summary> ''' <remarks></remarks> Private ReadOnly _foundFlags As SourceMemberFlags ''' <summary> ''' These are flags that are implied or computed ''' </summary> ''' <remarks></remarks> Private ReadOnly _computedFlags As SourceMemberFlags Public Sub New(foundFlags As SourceMemberFlags, computedFlags As SourceMemberFlags) _foundFlags = foundFlags _computedFlags = computedFlags End Sub Public ReadOnly Property FoundFlags As SourceMemberFlags Get Return _foundFlags End Get End Property Public ReadOnly Property ComputedFlags As SourceMemberFlags Get Return _computedFlags End Get End Property Public ReadOnly Property AllFlags As SourceMemberFlags Get Return _foundFlags Or _computedFlags End Get End Property End Structure End Namespace