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
Enabled debugging services in Roslyn branch #1428
Changes from 5 commits
5d1bd76
d9a24ca
262aef8
1d02edc
e7813d0
e209336
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
namespace Microsoft.VisualStudio.FSharp.Editor | ||
|
||
open System | ||
open System.Composition | ||
open System.Collections.Concurrent | ||
open System.Collections.Generic | ||
open System.Threading | ||
open System.Threading.Tasks | ||
open System.Linq | ||
|
||
open Microsoft.CodeAnalysis | ||
open Microsoft.CodeAnalysis.Classification | ||
open Microsoft.CodeAnalysis.Editor | ||
open Microsoft.CodeAnalysis.Editor.Implementation.Debugging | ||
open Microsoft.CodeAnalysis.Editor.Shared.Utilities | ||
open Microsoft.CodeAnalysis.Formatting | ||
open Microsoft.CodeAnalysis.Host.Mef | ||
open Microsoft.CodeAnalysis.Text | ||
|
||
open Microsoft.VisualStudio.FSharp.LanguageService | ||
open Microsoft.VisualStudio.Text | ||
open Microsoft.VisualStudio.Text.Tagging | ||
|
||
open Microsoft.FSharp.Compiler.Parser | ||
open Microsoft.FSharp.Compiler.SourceCodeServices | ||
open Microsoft.FSharp.Compiler.Range | ||
|
||
[<Shared>] | ||
[<ExportLanguageService(typeof<IBreakpointResolutionService>, FSharpCommonConstants.FSharpLanguageName)>] | ||
type internal FSharpBreakpointResolutionService() = | ||
|
||
static member GetBreakpointLocation(sourceText: SourceText, fileName: string, textSpan: TextSpan, options: FSharpProjectOptions) = async { | ||
let! parseResults = FSharpChecker.Instance.ParseFileInProject(fileName, sourceText.ToString(), options) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This is going to cause a large allocation every time due to the ToString. Are the results of parsing cached anywhere based on a SourceText value? For example if parsing a file with the same checksum just return previous parse. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. I don't see it being done on SourceText, just a memory allocation. I'll need to look into caching on our side if there was a performance issue in UX. |
||
let textLine = sourceText.Lines.GetLineFromPosition(textSpan.Start) | ||
|
||
let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based | ||
let textColumnNumber = textSpan.Start - textLine.Start | ||
|
||
return parseResults.ValidateBreakpointLocation(mkPos textLineNumber textColumnNumber) | ||
} | ||
|
||
interface IBreakpointResolutionService with | ||
member this.ResolveBreakpointAsync(document: Document, textSpan: TextSpan, cancellationToken: CancellationToken): Task<BreakpointResolutionResult> = | ||
let computation = async { | ||
let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project) | ||
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask | ||
let! location = FSharpBreakpointResolutionService.GetBreakpointLocation(sourceText, document.Name, textSpan, options) | ||
|
||
return match location with | ||
| None -> null | ||
| Some(range) -> BreakpointResolutionResult.CreateSpanResult(document, CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range)) | ||
} | ||
|
||
Async.StartAsTask(computation, TaskCreationOptions.None, cancellationToken).ContinueWith(fun(task: Task<BreakpointResolutionResult>) -> | ||
if task.Status = TaskStatus.RanToCompletion then | ||
task.Result | ||
else | ||
Assert.Exception(task.Exception.GetBaseException()) | ||
raise(task.Exception.GetBaseException()) | ||
, cancellationToken) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This helper seems to be used a lot. Factor it out into a separate function? |
||
|
||
// FSROSLYNTODO: enable placing breakpoints by when user suplies fully-qualified function names | ||
member this.ResolveBreakpointsAsync(_, _, _): Task<IEnumerable<BreakpointResolutionResult>> = | ||
Task.FromResult(Enumerable.Empty<BreakpointResolutionResult>()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is FSharpChecker an immutable type? If not and it contains mutable state consider passing this as a parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Static helper methods in service.fsi for parsing/type checking.