| File: Debugging\VisualBasicBreakpointService.vb | Web Access |
| Project: src\roslyn\src\Features\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Features.vbproj (Microsoft.CodeAnalysis.VisualBasic.Features) |
' 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.Composition Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Debugging Imports Microsoft.CodeAnalysis.ErrorReporting Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.EditAndContinue Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Debugging <ExportLanguageService(GetType(IBreakpointResolutionService), LanguageNames.VisualBasic), [Shared]> Friend NotInheritable Class VisualBasicBreakpointResolutionService Implements IBreakpointResolutionService <ImportingConstructor> <Obsolete(MefConstruction.ImportingConstructorMessage, True)> Public Sub New() End Sub Friend Shared Async Function GetBreakpointAsync(document As Document, position As Integer, length As Integer, cancellationToken As CancellationToken) As Task(Of BreakpointResolutionResult) Try Dim tree = Await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(False) If tree Is Nothing Then Return Nothing End If ' Non-zero length means that the span is passed by the debugger and we may need validate it. ' In a rare VB case, this span may contain multiple methods, e.g., ' ' [Sub Goo() Handles A ' ' End Sub ' ' Sub Bar() Handles B] ' ' End Sub ' ' It happens when IDE services (e.g., NavBar or CodeFix) inserts a new method at the beginning of the existing one ' which happens to have a breakpoint on its head. In this situation, we should attempt to validate the span of the existing method, ' not that of a newly-prepended method. If length > 0 Then Dim root = Await tree.GetRootAsync(cancellationToken).ConfigureAwait(False) Dim item = root.DescendantNodes( span:=New TextSpan(position, length), descendIntoChildren:=Function(n) Not n.IsKind(SyntaxKind.ConstructorBlock, SyntaxKind.SubBlock)). OfType(Of MethodBlockSyntax).Skip(1).LastOrDefault() If item IsNot Nothing Then position = item.SpanStart End If End If Dim span As TextSpan If Not BreakpointSpans.TryGetBreakpointSpan(tree, position, cancellationToken, span) Then Return Nothing End If If span.Length = 0 Then Return BreakpointResolutionResult.CreateLineResult(document) End If Return BreakpointResolutionResult.CreateSpanResult(document, span) Catch e As Exception When FatalError.ReportAndCatchUnlessCanceled(e, cancellationToken) Return Nothing End Try End Function Public Function ResolveBreakpointAsync(document As Document, textSpan As TextSpan, Optional cancellationToken As CancellationToken = Nothing) As Task(Of BreakpointResolutionResult) Implements IBreakpointResolutionService.ResolveBreakpointAsync Return GetBreakpointAsync(document, textSpan.Start, textSpan.Length, cancellationToken) End Function Public Function ResolveBreakpointsAsync( solution As Solution, name As String, Optional cancellationToken As CancellationToken = Nothing) As Task(Of IEnumerable(Of BreakpointResolutionResult)) Implements IBreakpointResolutionService.ResolveBreakpointsAsync Return New BreakpointResolver(solution, name).DoAsync(cancellationToken) End Function End Class End Namespace