Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure VB parser is disposed #76636

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/Compilers/VisualBasic/Portable/Scanner/Directives.vb
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Me.GetNextTokenInState(ScannerState.VB)

Else
Dim parser As New Parser(Me)

directiveTrivia = parser.ParseConditionalCompilationStatement()
directiveTrivia = parser.ConsumeStatementTerminatorAfterDirective(directiveTrivia)
Using parser = New Parser(Me)
ToddGrun marked this conversation as resolved.
Show resolved Hide resolved
directiveTrivia = parser.ParseConditionalCompilationStatement()
directiveTrivia = parser.ConsumeStatementTerminatorAfterDirective(directiveTrivia)
End Using
End If

Debug.Assert(directiveTrivia.FullWidth > 0, "should at least get #")
Expand Down
100 changes: 50 additions & 50 deletions src/Compilers/VisualBasic/Portable/Scanner/XmlDocComments.vb
Original file line number Diff line number Diff line change
Expand Up @@ -68,62 +68,62 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Me.MoveToNextSyntaxNodeInTrivia()

Else
Dim parser As New Parser(Me)

Me.IsScanningXmlDoc = True
Me._isStartingFirstXmlDocLine = True

' NOTE: Documentation comment syntax trivia must have at least one child xml node, because
' all the ['''] trivia are created as leading trivia for appropriate tokens.
' This means that we have to create at least one XmlText having trailing
' EOL to represent an empty documentation comment: ['''<eol>]
'
' The problem with this approach is that in presence of some errors (like
' not closed XML tags) we create missing tokens needed to represent the nodes
' *after* that last <eol> of the doc comment trivia, that means all the locations
' of created diagnostics will land on the first character of the next line
' after documentation comment
'
' To workaround this we parse XML nodes in two phases:
' - in the first phase we detect the last DocCommentLineBreak and create
' end-of-xml token instead; this should force all diagnostics to be
' reported on the next token location;
' - in the second phase we continue parsing XML nodes but don't create
' end-of-xml token which should just result in parsing one single node
' of XmlText type containing EOL;
' Then we merge the results and create resulting DocumentationCommentTrivia

' The first phase
Me._endOfXmlInsteadOfLastDocCommentLineBreak = True
Dim nodes = parser.ParseXmlContent(ScannerState.Content)

' The second phase
Me._endOfXmlInsteadOfLastDocCommentLineBreak = False
If nodes.Count = 0 AndAlso parser.CurrentToken.Kind = SyntaxKind.EndOfXmlToken Then
' This must be an empty documentation comment, we need to reset scanner so
' that the doc comment exterior trivia ([''']) lands on the final XmlNode

ResetLineBufferOffset()
restorePoint.RestoreTokens(includeLookAhead:=False)
Using parser = New Parser(Me)
ToddGrun marked this conversation as resolved.
Show resolved Hide resolved
Me.IsScanningXmlDoc = True
Me._isStartingFirstXmlDocLine = True
End If

nodes = parser.ParseRestOfDocCommentContent(nodes)
Me.IsScanningXmlDoc = False
' NOTE: Documentation comment syntax trivia must have at least one child xml node, because
' all the ['''] trivia are created as leading trivia for appropriate tokens.
' This means that we have to create at least one XmlText having trailing
' EOL to represent an empty documentation comment: ['''<eol>]
'
' The problem with this approach is that in presence of some errors (like
' not closed XML tags) we create missing tokens needed to represent the nodes
' *after* that last <eol> of the doc comment trivia, that means all the locations
' of created diagnostics will land on the first character of the next line
' after documentation comment
'
' To workaround this we parse XML nodes in two phases:
' - in the first phase we detect the last DocCommentLineBreak and create
' end-of-xml token instead; this should force all diagnostics to be
' reported on the next token location;
' - in the second phase we continue parsing XML nodes but don't create
' end-of-xml token which should just result in parsing one single node
' of XmlText type containing EOL;
' Then we merge the results and create resulting DocumentationCommentTrivia

' The first phase
Me._endOfXmlInsteadOfLastDocCommentLineBreak = True
Dim nodes = parser.ParseXmlContent(ScannerState.Content)

' The second phase
Me._endOfXmlInsteadOfLastDocCommentLineBreak = False
If nodes.Count = 0 AndAlso parser.CurrentToken.Kind = SyntaxKind.EndOfXmlToken Then
' This must be an empty documentation comment, we need to reset scanner so
' that the doc comment exterior trivia ([''']) lands on the final XmlNode

ResetLineBufferOffset()
restorePoint.RestoreTokens(includeLookAhead:=False)
Me._isStartingFirstXmlDocLine = True
End If

nodes = parser.ParseRestOfDocCommentContent(nodes)
Me.IsScanningXmlDoc = False

Debug.Assert(nodes.Any)
Debug.Assert(nodes(0).FullWidth > 0, "should at least get {'''EoL} ")
Debug.Assert(nodes.Any)
Debug.Assert(nodes(0).FullWidth > 0, "should at least get {'''EoL} ")

' restore _currentToken and lookahead,
' but keep offset and PP state
ResetLineBufferOffset()
' restore _currentToken and lookahead,
' but keep offset and PP state
ResetLineBufferOffset()

docCommentSyntax = SyntaxFactory.DocumentationCommentTrivia(nodes)
docCommentSyntax = SyntaxFactory.DocumentationCommentTrivia(nodes)

If Me.Options.DocumentationMode < DocumentationMode.Diagnose Then
' All diagnostics coming from documentation comment are ignored
docCommentSyntax.ClearFlags(GreenNode.NodeFlags.ContainsDiagnostics)
End If
If Me.Options.DocumentationMode < DocumentationMode.Diagnose Then
' All diagnostics coming from documentation comment are ignored
docCommentSyntax.ClearFlags(GreenNode.NodeFlags.ContainsDiagnostics)
End If
End Using
End If

' RESTORE lookahead state and current token if there were any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,17 +292,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Using scanner As New InternalSyntax.Scanner(MakeSourceText(text, 0), VisualBasicParseOptions.Default) ' NOTE: Default options should be enough
scanner.ForceScanningXmlDocMode()

Dim parser = New InternalSyntax.Parser(scanner)
parser.GetNextToken(InternalSyntax.ScannerState.Element)
Using parser = New InternalSyntax.Parser(scanner)
parser.GetNextToken(InternalSyntax.ScannerState.Element)

Dim xmlName = InternalSyntax.SyntaxFactory.XmlName(
Dim xmlName = InternalSyntax.SyntaxFactory.XmlName(
Nothing, InternalSyntax.SyntaxFactory.XmlNameToken(parentElementName, SyntaxKind.XmlNameToken, Nothing, Nothing))

Return DirectCast(
Return DirectCast(
parser.ParseXmlAttribute(
requireLeadingWhitespace:=False,
AllowNameAsExpression:=False,
xmlElementName:=xmlName).CreateRed(Nothing, 0), BaseXmlAttributeSyntax)
End Using
End Using
End Function

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic

Dim node As InternalSyntax.CompilationUnitSyntax
Using scanner
node = New Parser(scanner).ParseCompilationUnit()
Using parser = New Parser(scanner)
node = parser.ParseCompilationUnit()
End Using
End Using

Dim root = DirectCast(node.CreateRed(Nothing, 0), CompilationUnitSyntax)
Expand Down