Skip to content

Commit

Permalink
fix cancellation warnings (#3077)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsyme authored and KevinRansom committed May 18, 2017
1 parent f09f727 commit 6f5b2c4
Show file tree
Hide file tree
Showing 18 changed files with 70 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type internal FSharpColorizationService
member this.AddSyntacticClassificationsAsync(document: Document, textSpan: TextSpan, result: List<ClassifiedSpan>, cancellationToken: CancellationToken) =
async {
let defines = projectInfoManager.GetCompilationDefinesForEditingDocument(document)
let! sourceText = document.GetTextAsync(cancellationToken)
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
result.AddRange(Tokenizer.getColorizationData(document.Id, sourceText, textSpan, Some(document.FilePath), defines, cancellationToken))
} |> RoslynHelpers.StartAsyncUnitAsTask cancellationToken

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ type internal FSharpAddNewKeywordCodeFixProvider() =
title,
(fun (cancellationToken: CancellationToken) ->
async {
let! sourceText = context.Document.GetTextAsync()
let! cancellationToken = Async.CancellationToken
let! sourceText = context.Document.GetTextAsync(cancellationToken) |> Async.AwaitTask
return context.Document.WithText(sourceText.WithChanges(TextChange(TextSpan(context.Span.Start, 0), "new ")))
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title), context.Diagnostics |> Seq.filter (fun x -> this.FixableDiagnosticIds.Contains x.Id) |> Seq.toImmutableArray)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ type internal FSharpAddOpenCodeFixProvider
fixUnderscoresInMenuText fullName,
fun (cancellationToken: CancellationToken) ->
async {
let! sourceText = context.Document.GetTextAsync()
let! cancellationToken = Async.CancellationToken
let! sourceText = context.Document.GetTextAsync(cancellationToken) |> Async.AwaitTask
return context.Document.WithText(sourceText.Replace(context.Span, qualifier))
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken))

Expand All @@ -49,7 +50,8 @@ type internal FSharpAddOpenCodeFixProvider
fixUnderscoresInMenuText displayText,
(fun (cancellationToken: CancellationToken) ->
async {
let! sourceText = context.Document.GetTextAsync()
let! cancellationToken = Async.CancellationToken
let! sourceText = context.Document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let changedText, _ = OpenDeclarationHelper.insertOpenDeclaration sourceText ctx ns
return context.Document.WithText(changedText)
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ type internal FSharpImplementInterfaceCodeFixProvider
title,
(fun (cancellationToken: CancellationToken) ->
async {
let! sourceText = context.Document.GetTextAsync() |> Async.AwaitTask
let! sourceText = context.Document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let getMemberByLocation(name, range: range) =
let lineStr = sourceText.Lines.[range.EndLine-1].ToString()
results.GetSymbolUseAtLocation(range.EndLine, range.EndColumn, lineStr, [name], userOpName=userOpName)
Expand Down
3 changes: 2 additions & 1 deletion vsintegration/src/FSharp.Editor/CodeFix/RenameUnusedValue.fs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ type internal FSharpRenameUnusedValueCodeFixProvider
title,
(fun (cancellationToken: CancellationToken) ->
async {
let! sourceText = context.Document.GetTextAsync()
let! cancellationToken = Async.CancellationToken
let! sourceText = context.Document.GetTextAsync(cancellationToken) |> Async.AwaitTask
return context.Document.WithText(sourceText.WithChanges(textChange))
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ type internal FSharpReplaceWithSuggestionCodeFixProvider() =
title,
(fun (cancellationToken: CancellationToken) ->
async {
let! sourceText = context.Document.GetTextAsync()
let! cancellationToken = Async.CancellationToken
let! sourceText = context.Document.GetTextAsync(cancellationToken) |> Async.AwaitTask
return context.Document.WithText(sourceText.WithChanges(textChange))
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title)
Expand Down
3 changes: 2 additions & 1 deletion vsintegration/src/FSharp.Editor/CodeFix/SimplifyName.fs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ type internal FSharpSimplifyNameCodeFixProvider() =
title,
(fun (cancellationToken: CancellationToken) ->
async {
let! sourceText = context.Document.GetTextAsync()
let! cancellationToken = Async.CancellationToken
let! sourceText = context.Document.GetTextAsync(cancellationToken) |> Async.AwaitTask
return context.Document.WithText(sourceText.WithChanges(textChange))
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title)
Expand Down
9 changes: 0 additions & 9 deletions vsintegration/src/FSharp.Editor/Common/Pervasive.fs
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,4 @@ module Async =
async { return! agent.PostAndAsyncReply id }


type AsyncBuilder with
member __.Bind(computation: System.Threading.Tasks.Task<'a>, binder: 'a -> Async<'b>): Async<'b> =
async {
let! a = Async.AwaitTask computation
return! binder a
}

member __.ReturnFrom(computation: System.Threading.Tasks.Task<'a>): Async<'a> = Async.AwaitTask computation


33 changes: 23 additions & 10 deletions vsintegration/src/FSharp.Editor/Common/RoslynHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Microsoft.VisualStudio.FSharp.Editor
open System
open System.Collections.Immutable
open System.Collections.Generic
open System.Threading
open System.Threading.Tasks
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.Text
Expand Down Expand Up @@ -85,16 +86,28 @@ module internal RoslynHelpers =

let CollectTaggedText (list: List<_>) (t:TaggedText) = list.Add(TaggedText(roslynTag t.Tag, t.Text))

let StartAsyncAsTask cancellationToken computation =
let computation =
async {
try
return! computation
with e ->
Assert.Exception(e)
return Unchecked.defaultof<_>
}
Async.StartAsTask(computation, TaskCreationOptions.None, cancellationToken)
type VolatileBarrier() =
[<VolatileField>]
let mutable isStopped = false
member __.Proceed = not isStopped
member __.Stop() = isStopped <- true

// This is like Async.StartAsTask, but if cancellation occurs we explicitly associate the cancellation with cancellationToken
let StartAsyncAsTask (cancellationToken: CancellationToken) computation =
let tcs = new TaskCompletionSource<_>(TaskCreationOptions.None)
let barrier = VolatileBarrier()
let reg = cancellationToken.Register(fun _ -> if barrier.Proceed then tcs.TrySetCanceled(cancellationToken) |> ignore)
let task = tcs.Task
let disposeReg() = barrier.Stop(); if not task.IsCanceled then reg.Dispose()
Async.StartWithContinuations(
async { do! Async.SwitchToThreadPool()
return! computation },
continuation=(fun result -> disposeReg(); tcs.TrySetResult(result) |> ignore),
exceptionContinuation=(function :? OperationCanceledException -> disposeReg(); tcs.TrySetCanceled(cancellationToken) |> ignore
| exn -> disposeReg(); tcs.TrySetException(exn) |> ignore),
cancellationContinuation=(fun _oce -> disposeReg(); tcs.TrySetCanceled(cancellationToken) |> ignore),
cancellationToken=cancellationToken)
task

let StartAsyncUnitAsTask cancellationToken (computation:Async<unit>) =
StartAsyncAsTask cancellationToken computation :> Task
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ type internal FSharpLanguageDebugInfoService [<ImportingConstructor>](projectInf
member this.GetDataTipInfoAsync(document: Document, position: int, cancellationToken: CancellationToken): Task<DebugDataTipInfo> =
async {
let defines = projectInfoManager.GetCompilationDefinesForEditingDocument(document)
let! sourceText = document.GetTextAsync(cancellationToken)
let! cancellationToken = Async.CancellationToken
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let textSpan = TextSpan.FromBounds(0, sourceText.Length)
let tokens = Tokenizer.getColorizationData(document.Id, sourceText, textSpan, Some(document.Name), defines, cancellationToken)
let result =
Expand Down
11 changes: 6 additions & 5 deletions vsintegration/src/FSharp.Editor/Formatting/IndentationService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ type internal FSharpIndentationService() =
interface ISynchronousIndentationService with
member this.GetDesiredIndentation(document: Document, lineNumber: int, cancellationToken: CancellationToken): Nullable<IndentationResult> =
async {
let! sourceText = document.GetTextAsync(cancellationToken)
let! options = document.GetOptionsAsync(cancellationToken)
let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpConstants.FSharpLanguageName)
let! cancellationToken = Async.CancellationToken
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let! options = document.GetOptionsAsync(cancellationToken) |> Async.AwaitTask
let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpConstants.FSharpLanguageName)

return
return
match FSharpIndentationService.GetDesiredIndentation(sourceText, lineNumber, tabSize) with
| None -> Nullable()
| Some(indentation) -> Nullable<IndentationResult>(IndentationResult(sourceText.Lines.[lineNumber].Start, indentation))
} |> Async.RunSynchronously
} |> (fun c -> Async.RunSynchronously(c,cancellationToken=cancellationToken))
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type internal InlineRenameLocationSet(locationsByDocument: DocumentLocations [],
return solution
else
let doc = locationsByDocument.[i]
let! oldSourceText = doc.Document.GetTextAsync(cancellationToken)
let! oldSourceText = doc.Document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let changes = doc.Locations |> Seq.map (fun loc -> TextChange(loc.TextSpan, replacementText))
let newSource = oldSourceText.WithChanges(changes)
return! applyChanges (i + 1) (solution.WithDocumentText(doc.Document.Id, newSource))
Expand Down Expand Up @@ -122,7 +122,8 @@ type internal InlineRenameInfo
|> Seq.map (fun (KeyValue(documentId, symbolUses)) ->
async {
let document = document.Project.Solution.GetDocument(documentId)
let! sourceText = document.GetTextAsync(cancellationToken)
let! cancellationToken = Async.CancellationToken
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let locations =
symbolUses
|> Array.map (fun symbolUse ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ type FSharpChecker with
let! cancellationToken = Async.CancellationToken
let! sourceText =
match sourceText with
| Some x -> Task.FromResult x
| None -> document.GetTextAsync()
let! textVersion = document.GetTextVersionAsync(cancellationToken)
| Some x -> async.Return x
| None -> document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let! textVersion = document.GetTextVersionAsync(cancellationToken) |> Async.AwaitTask
return! checker.ParseAndCheckDocument(document.FilePath, textVersion.GetHashCode(), sourceText.ToString(), options, allowStaleResults, userOpName=userOpName)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ type internal ProjectInfoManager
try
let fileName = document.FilePath
let! cancellationToken = Async.CancellationToken
let! sourceText = document.GetTextAsync(cancellationToken)
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
// NOTE: we don't use FCS cross-project references from scripts to projects. The projects must have been
// compiled and #r will refer to files on disk.
let tryGetOrCreateProjectId _ = None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ module internal SymbolHelpers =

for KeyValue(documentId, symbolUses) in symbolUsesByDocumentId do
let document = document.Project.Solution.GetDocument(documentId)
let! sourceText = document.GetTextAsync(cancellationToken)
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
let mutable sourceText = sourceText
for symbolUse in symbolUses do
let textSpan = Tokenizer.fixupSpan(sourceText, RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate))
Expand Down
11 changes: 6 additions & 5 deletions vsintegration/src/FSharp.Editor/Navigation/FindUsagesService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type internal FSharpFindUsagesService
static let userOpName = "FindUsages"

// File can be included in more than one project, hence single `range` may results with multiple `Document`s.
let rangeToDocumentSpans (solution: Solution, range: range, cancellationToken: CancellationToken) =
let rangeToDocumentSpans (solution: Solution, range: range) =
async {
if range.Start = range.End then return []
else
Expand All @@ -35,7 +35,8 @@ type internal FSharpFindUsagesService
|> Seq.map (fun documentId ->
async {
let doc = solution.GetDocument(documentId)
let! sourceText = doc.GetTextAsync(cancellationToken)
let! cancellationToken = Async.CancellationToken
let! sourceText = doc.GetTextAsync(cancellationToken) |> Async.AwaitTask
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range) with
| Some span ->
let span = Tokenizer.fixupSpan(sourceText, span)
Expand All @@ -48,7 +49,7 @@ type internal FSharpFindUsagesService

let findReferencedSymbolsAsync(document: Document, position: int, context: IFindUsagesContext, allReferences: bool, userOpName: string) : Async<unit> =
asyncMaybe {
let! sourceText = document.GetTextAsync(context.CancellationToken)
let! sourceText = document.GetTextAsync(context.CancellationToken) |> Async.AwaitTask |> liftAsync
let checker = checkerProvider.Checker
let! options = projectInfoManager.TryGetOptionsForDocumentOrProject(document)
let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, options, sourceText = sourceText, allowStaleResults = true, userOpName = userOpName)
Expand All @@ -70,7 +71,7 @@ type internal FSharpFindUsagesService
async {
let! declarationSpans =
match declarationRange with
| Some range -> rangeToDocumentSpans(document.Project.Solution, range, context.CancellationToken)
| Some range -> rangeToDocumentSpans(document.Project.Solution, range)
| None -> async.Return []

return
Expand Down Expand Up @@ -129,7 +130,7 @@ type internal FSharpFindUsagesService
| _ ->
// report a reference if we're interested in all _or_ if we're looking at an implementation
if allReferences || symbolUse.IsFromDispatchSlotImplementation then
let! referenceDocSpans = rangeToDocumentSpans(document.Project.Solution, symbolUse.RangeAlternate, context.CancellationToken) |> liftAsync
let! referenceDocSpans = rangeToDocumentSpans(document.Project.Solution, symbolUse.RangeAlternate) |> liftAsync
match referenceDocSpans with
| [] -> ()
| _ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ type internal GoToDefinition(checker: FSharpChecker, projectInfoManager: Project
if not refDocumentIds.IsEmpty then
let refDocumentId = refDocumentIds.First()
let refDocument = document.Project.Solution.GetDocument refDocumentId
let! refSourceText = refDocument.GetTextAsync()
let! cancellationToken = Async.CancellationToken
let! refSourceText = refDocument.GetTextAsync(cancellationToken) |> Async.AwaitTask
let refTextSpan = RoslynHelpers.FSharpRangeToTextSpan (refSourceText, range)
return Some (FSharpNavigableItem (refDocument, refTextSpan))
else return None
Expand Down
Loading

0 comments on commit 6f5b2c4

Please sign in to comment.