/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Parser/BlockContexts/DeclarationContext.vb
484 строки
21 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 Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Syntax '----------------------------------------------------------------------------- ' Contains the definition of the DeclarationContext '----------------------------------------------------------------------------- Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax Friend MustInherit Class DeclarationContext Inherits BlockContext Friend Sub New(kind As SyntaxKind, statement As StatementSyntax, context As BlockContext) MyBase.New(kind, statement, context) End Sub Friend Overrides Function Parse() As StatementSyntax Return Parser.ParseDeclarationStatement() End Function Friend Overrides Function ProcessSyntax(node As VisualBasicSyntaxNode) As BlockContext Dim kind As SyntaxKind = node.Kind Dim methodBlockKind As SyntaxKind Dim methodBase As MethodBaseSyntax Select Case kind Case SyntaxKind.NamespaceStatement ' davidsch - This error check used to be in ParseDeclarations 'In dev10 the error was only on the keyword and not the full statement Dim reportAnError As Boolean = True Dim infos As DiagnosticInfo() = node.GetDiagnostics() If infos IsNot Nothing Then For Each info In infos Select Case info.Code Case ERRID.ERR_NamespaceNotAtNamespace, ERRID.ERR_InvInsideEndsProc reportAnError = False Exit For End Select Next End If If reportAnError Then node = Parser.ReportSyntaxError(node, ERRID.ERR_NamespaceNotAtNamespace) End If Dim context = Me.PrevBlock RecoverFromMissingEnd(context) 'Let the outer context process this statement Return context.ProcessSyntax(node) Case SyntaxKind.ModuleStatement 'In dev10 the error was only on the keyword and not the full statement node = Parser.ReportSyntaxError(node, ERRID.ERR_ModuleNotAtNamespace) Return New TypeBlockContext(SyntaxKind.ModuleBlock, DirectCast(node, StatementSyntax), Me) Case SyntaxKind.EnumStatement Return New EnumDeclarationBlockContext(DirectCast(node, StatementSyntax), Me) Case SyntaxKind.ClassStatement Return New TypeBlockContext(SyntaxKind.ClassBlock, DirectCast(node, StatementSyntax), Me) Case SyntaxKind.StructureStatement Return New TypeBlockContext(SyntaxKind.StructureBlock, DirectCast(node, StatementSyntax), Me) Case SyntaxKind.InterfaceStatement Return New InterfaceDeclarationBlockContext(DirectCast(node, StatementSyntax), Me) Case SyntaxKind.SubStatement methodBlockKind = SyntaxKind.SubBlock GoTo HandleMethodBase Case SyntaxKind.SubNewStatement methodBlockKind = SyntaxKind.ConstructorBlock GoTo HandleMethodBase Case SyntaxKind.FunctionStatement methodBlockKind = SyntaxKind.FunctionBlock HandleMethodBase: If Not Parser.IsFirstStatementOnLine(node.GetFirstToken) Then node = Parser.ReportSyntaxError(node, ERRID.ERR_MethodMustBeFirstStatementOnLine) End If ' Don't create blocks for MustOverride Sub, Function, and New methods methodBase = DirectCast(node, MethodBaseSyntax) If Not methodBase.Modifiers.Any(SyntaxKind.MustOverrideKeyword) Then Return New MethodBlockContext(methodBlockKind, methodBase, Me) End If Add(node) Case SyntaxKind.OperatorStatement If Not Parser.IsFirstStatementOnLine(node.GetFirstToken) Then node = Parser.ReportSyntaxError(node, ERRID.ERR_MethodMustBeFirstStatementOnLine) End If ' It is a syntax error to have an operator in a module ' This error is reported in declared in Dev10 If Me.BlockKind = SyntaxKind.ModuleBlock Then node = Parser.ReportSyntaxError(node, ERRID.ERR_OperatorDeclaredInModule) End If Return New MethodBlockContext(SyntaxKind.OperatorBlock, DirectCast(node, StatementSyntax), Me) Case SyntaxKind.PropertyStatement ' ===== Make an initial attempt at determining if this might be an auto or expanded property ' We can determine which it is in some cases by looking at the specifiers. Dim propertyStatement = DirectCast(node, PropertyStatementSyntax) Dim modifiers = propertyStatement.Modifiers Dim isPropertyBlock As Boolean = False If modifiers.Any Then If modifiers.Any(SyntaxKind.MustOverrideKeyword) Then ' Mustoverride mean that the property doesn't have any implementation ' This cannot be an auto property so the property may not be initialized. ' Check if initializer exists. Only auto properties may have initialization. node = PropertyBlockContext.ReportErrorIfHasInitializer(DirectCast(node, PropertyStatementSyntax)) Add(node) Exit Select Else isPropertyBlock = modifiers.Any(SyntaxKind.DefaultKeyword, SyntaxKind.IteratorKeyword) End If End If Return New PropertyBlockContext(propertyStatement, Me, isPropertyBlock) Case _ SyntaxKind.SetAccessorStatement, SyntaxKind.GetAccessorStatement, SyntaxKind.AddHandlerAccessorStatement, SyntaxKind.RemoveHandlerAccessorStatement, SyntaxKind.RaiseEventAccessorStatement 'TODO - davidsch - ParseSpecifierDeclaration reports ERRID_ExpectedDeclaration but ParsePropertyOrEventProcedureDefinition reports ERRID_Syntax. ' ERRID_ExpectedDeclaration seems like a better error message. node = Parser.ReportSyntaxError(node, ERRID.ERR_ExpectedDeclaration) Add(node) Case SyntaxKind.EventStatement Dim eventDecl = DirectCast(node, EventStatementSyntax) ' Per Dev10, build a block event only if all the requirements for one are met, ' i.e. custom modifier and a real AsClause If eventDecl.CustomKeyword IsNot Nothing Then If eventDecl.AsClause.AsKeyword.IsMissing Then ' 'Custom' modifier invalid on event declared without an explicit delegate type. ' davidsch - Dev10 put this error on the custom keyword. node = Parser.ReportSyntaxError(eventDecl, ERRID.ERR_CustomEventRequiresAs) Else Return New EventBlockContext(eventDecl, Me) End If End If Add(node) Case SyntaxKind.AttributesStatement node = Parser.ReportSyntaxError(node, ERRID.ERR_AttributeStmtWrongOrder) Add(node) Case SyntaxKind.OptionStatement node = Parser.ReportSyntaxError(node, ERRID.ERR_OptionStmtWrongOrder) Add(node) Case SyntaxKind.ImportsStatement node = Parser.ReportSyntaxError(node, ERRID.ERR_ImportsMustBeFirst) Add(node) Case SyntaxKind.InheritsStatement Dim beginStatement = Me.BeginStatement If beginStatement IsNot Nothing AndAlso beginStatement.Kind = SyntaxKind.InterfaceStatement Then node = Parser.ReportSyntaxError(node, ERRID.ERR_BadInterfaceOrderOnInherits) Else node = Parser.ReportSyntaxError(node, ERRID.ERR_InheritsStmtWrongOrder) End If Add(node) Case SyntaxKind.ImplementsStatement node = Parser.ReportSyntaxError(node, ERRID.ERR_ImplementsStmtWrongOrder) Add(node) Case _ SyntaxKind.EnumBlock, SyntaxKind.ClassBlock, SyntaxKind.ModuleBlock, SyntaxKind.NamespaceBlock, SyntaxKind.StructureBlock, SyntaxKind.InterfaceBlock, SyntaxKind.SubBlock, SyntaxKind.ConstructorBlock, SyntaxKind.FunctionBlock, SyntaxKind.OperatorBlock, SyntaxKind.PropertyBlock, SyntaxKind.EventBlock 'TODO - Does parser create Constructors? Verify that code was ported correctly. ' Handle any block that can be created by this context Add(node) Case _ SyntaxKind.EmptyStatement, SyntaxKind.IncompleteMember, SyntaxKind.FieldDeclaration, SyntaxKind.DelegateSubStatement, SyntaxKind.DelegateFunctionStatement, SyntaxKind.DeclareSubStatement, SyntaxKind.DeclareFunctionStatement, SyntaxKind.EnumMemberDeclaration Add(node) Case SyntaxKind.LabelStatement node = Parser.ReportSyntaxError(node, ERRID.ERR_InvOutsideProc) Add(node) Case _ SyntaxKind.EndStatement, SyntaxKind.StopStatement ' an error has already been reported by ParseGroupEndStatement Add(node) Case Else ' Do not report an error on End statements - it is reported on the block begin statement ' or an error that the beginning statement is missing is reported. If Not SyntaxFacts.IsEndBlockLoopOrNextStatement(node.Kind) Then Debug.Assert(IsExecutableStatementOrItsPart(node)) node = Parser.ReportSyntaxError(node, ERRID.ERR_ExecutableAsDeclaration) End If Add(node) End Select Return Me End Function Friend Overrides Function TryLinkSyntax(node As VisualBasicSyntaxNode, ByRef newContext As BlockContext) As LinkResult newContext = Nothing ' block-ending statements are always safe to reuse and are very common If KindEndsBlock(node.Kind) Then Return UseSyntax(node, newContext) End If Select Case node.Kind Case _ SyntaxKind.NamespaceStatement, SyntaxKind.ModuleStatement, SyntaxKind.EnumStatement, SyntaxKind.ClassStatement, SyntaxKind.StructureStatement, SyntaxKind.InterfaceStatement, SyntaxKind.SubStatement, SyntaxKind.SubNewStatement, SyntaxKind.FunctionStatement, SyntaxKind.OperatorStatement, SyntaxKind.PropertyStatement, SyntaxKind.SetAccessorStatement, SyntaxKind.GetAccessorStatement, SyntaxKind.AddHandlerAccessorStatement, SyntaxKind.RemoveHandlerAccessorStatement, SyntaxKind.RaiseEventAccessorStatement, SyntaxKind.EventStatement, SyntaxKind.AttributesStatement, SyntaxKind.OptionStatement, SyntaxKind.ImportsStatement, SyntaxKind.InheritsStatement, SyntaxKind.ImplementsStatement Return UseSyntax(node, newContext) Case _ SyntaxKind.FieldDeclaration, SyntaxKind.DelegateSubStatement, SyntaxKind.DelegateFunctionStatement, SyntaxKind.DeclareSubStatement, SyntaxKind.DeclareFunctionStatement, SyntaxKind.EnumMemberDeclaration Return UseSyntax(node, newContext) Case _ SyntaxKind.ClassBlock, SyntaxKind.StructureBlock, SyntaxKind.InterfaceBlock Return UseSyntax(node, newContext, DirectCast(node, TypeBlockSyntax).EndBlockStatement.IsMissing) Case SyntaxKind.EnumBlock Return UseSyntax(node, newContext, DirectCast(node, EnumBlockSyntax).EndEnumStatement.IsMissing) Case _ SyntaxKind.SubBlock, SyntaxKind.ConstructorBlock, SyntaxKind.FunctionBlock Return UseSyntax(node, newContext, DirectCast(node, MethodBlockBaseSyntax).End.IsMissing) Case SyntaxKind.OperatorBlock If Me.BlockKind = SyntaxKind.ModuleBlock Then ' Crumble if this is in a module block for correct error processing newContext = Me Return LinkResult.Crumble End If Return UseSyntax(node, newContext, DirectCast(node, OperatorBlockSyntax).End.IsMissing) Case SyntaxKind.EventBlock Return UseSyntax(node, newContext, DirectCast(node, EventBlockSyntax).EndEventStatement.IsMissing) Case SyntaxKind.PropertyBlock Return UseSyntax(node, newContext, DirectCast(node, PropertyBlockSyntax).EndPropertyStatement.IsMissing) Case _ SyntaxKind.NamespaceBlock, SyntaxKind.ModuleBlock ' Crumble to handle errors for NamespaceBlock and ModuleBlock. newContext = Me Return LinkResult.Crumble ' single line If gets parsed as unexpected If + some garbage ' when in declaration context so cannot be reused ' see bug 901645 Case SyntaxKind.SingleLineIfStatement newContext = Me Return LinkResult.Crumble Case SyntaxKind.LocalDeclarationStatement ' Crumble so they become field declarations newContext = Me Return LinkResult.Crumble ' TODO: need to add all executable statements that ParseDeclarationStatement handle as unexpected executables ' Move error reporting from ParseDeclarationStatement to the context. Case SyntaxKind.IfStatement node = Parser.ReportSyntaxError(node, ERRID.ERR_ExecutableAsDeclaration) Return TryUseStatement(node, newContext) ' by default statements are not handled in declaration context Case Else newContext = Me Return LinkResult.NotUsed End Select End Function Friend Overrides Function RecoverFromMismatchedEnd(statement As StatementSyntax) As BlockContext Debug.Assert(statement IsNot Nothing) ' // The end construct is extraneous. Report an error and leave ' // the current context alone. Dim ErrorId As ERRID = ERRID.ERR_Syntax Dim stmtKind = statement.Kind Select Case (stmtKind) Case SyntaxKind.EndIfStatement ErrorId = ERRID.ERR_EndIfNoMatchingIf Case SyntaxKind.EndWithStatement ErrorId = ERRID.ERR_EndWithWithoutWith Case SyntaxKind.EndSelectStatement ErrorId = ERRID.ERR_EndSelectNoSelect Case SyntaxKind.EndWhileStatement ErrorId = ERRID.ERR_EndWhileNoWhile Case SyntaxKind.SimpleLoopStatement, SyntaxKind.LoopWhileStatement, SyntaxKind.LoopUntilStatement ErrorId = ERRID.ERR_LoopNoMatchingDo Case SyntaxKind.NextStatement ErrorId = ERRID.ERR_NextNoMatchingFor Case SyntaxKind.EndSubStatement ErrorId = ERRID.ERR_InvalidEndSub Case SyntaxKind.EndFunctionStatement ErrorId = ERRID.ERR_InvalidEndFunction Case SyntaxKind.EndOperatorStatement ErrorId = ERRID.ERR_InvalidEndOperator Case SyntaxKind.EndPropertyStatement ErrorId = ERRID.ERR_InvalidEndProperty Case SyntaxKind.EndGetStatement ErrorId = ERRID.ERR_InvalidEndGet Case SyntaxKind.EndSetStatement ErrorId = ERRID.ERR_InvalidEndSet Case SyntaxKind.EndEventStatement ErrorId = ERRID.ERR_InvalidEndEvent Case SyntaxKind.EndAddHandlerStatement ErrorId = ERRID.ERR_InvalidEndAddHandler Case SyntaxKind.EndRemoveHandlerStatement ErrorId = ERRID.ERR_InvalidEndRemoveHandler Case SyntaxKind.EndRaiseEventStatement ErrorId = ERRID.ERR_InvalidEndRaiseEvent Case SyntaxKind.EndStructureStatement ErrorId = ERRID.ERR_EndStructureNoStructure Case SyntaxKind.EndEnumStatement ErrorId = ERRID.ERR_InvalidEndEnum Case SyntaxKind.EndInterfaceStatement ErrorId = ERRID.ERR_InvalidEndInterface Case SyntaxKind.EndTryStatement ErrorId = ERRID.ERR_EndTryNoTry Case SyntaxKind.EndClassStatement ErrorId = ERRID.ERR_EndClassNoClass Case SyntaxKind.EndModuleStatement ErrorId = ERRID.ERR_EndModuleNoModule Case SyntaxKind.EndNamespaceStatement ErrorId = ERRID.ERR_EndNamespaceNoNamespace Case SyntaxKind.EndUsingStatement ErrorId = ERRID.ERR_EndUsingWithoutUsing Case SyntaxKind.EndSyncLockStatement ErrorId = ERRID.ERR_EndSyncLockNoSyncLock #If UNDONE Then 'TODO - davidsch - handle regions Case NodeKind.EndRegionStatement ErrorId = ERRID.ERR_EndRegionNoRegion #End If Case SyntaxKind.EmptyStatement, SyntaxKind.IncompleteMember ErrorId = ERRID.ERR_UnrecognizedEnd Case Else Throw New ArgumentException("Statement must be an end block statement") End Select 'TODO ' Should ReportSyntaxError be on the Parser or can it be made static ' If the parser isn't needed for more than this then remove it from the context. statement = Parser.ReportSyntaxError(statement, ErrorId) Return ProcessSyntax(statement) End Function Friend Overrides Function EndBlock(endStmt As StatementSyntax) As BlockContext Dim blockSyntax = CreateBlockSyntax(endStmt) Dim context = PrevBlock.ProcessSyntax(blockSyntax) Return context End Function Friend Overrides Function ProcessStatementTerminator(lambdaContext As BlockContext) As BlockContext Parser.ConsumeStatementTerminator(colonAsSeparator:=False) Return Me End Function Friend Overrides ReadOnly Property IsSingleLine As Boolean Get Return False End Get End Property End Class End Namespace