Skip to content

Commit 517ce91

Browse files
author
Omar Tawfik
committed
Added GetDescriptionAsync()
1 parent 4ecfb00 commit 517ce91

File tree

7 files changed

+73
-14
lines changed

7 files changed

+73
-14
lines changed

vsintegration/src/FSharp.Editor/ColorizationService.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ type internal FSharpColorizationService() =
153153
let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project)
154154
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
155155
let! parseResults = FSharpChecker.Instance.ParseFileInProject(document.Name, sourceText.ToString(), options)
156-
let! checkResultsAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, document.Name, 0, textSpan.ToString(), options)
156+
let! textVersion = document.GetTextVersionAsync(cancellationToken) |> Async.AwaitTask
157+
let! checkResultsAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, document.Name, textVersion.GetHashCode(), textSpan.ToString(), options)
157158
158159
let extraColorizationData = match checkResultsAnswer with
159160
| FSharpCheckFileAnswer.Aborted -> failwith "Compilation isn't complete yet"

vsintegration/src/FSharp.Editor/CommonRoslynHelpers.fs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ module internal CommonRoslynHelpers =
1818
let endPosition = sourceText.Lines.[range.EndLine - 1].Start + range.EndColumn
1919
TextSpan(startPosition, endPosition - startPosition)
2020

21+
let GetTaskAction(computation: Async<unit>) =
22+
// Shortcut due to nonstandard way of converting Async<unit> to Task
23+
let action() =
24+
try
25+
computation |> Async.RunSynchronously
26+
with ex ->
27+
Assert.Exception(ex.GetBaseException())
28+
raise(ex.GetBaseException())
29+
Action action
30+
2131
let GetCompletedTaskResult(task: Task<'TResult>) =
2232
if task.Status = TaskStatus.RanToCompletion then
2333
task.Result

vsintegration/src/FSharp.Editor/CompletionProvider.fs

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ open System
66
open System.Composition
77
open System.Collections.Concurrent
88
open System.Collections.Generic
9+
open System.Collections.Immutable
910
open System.Threading
1011
open System.Threading.Tasks
1112
open System.Linq
13+
open System.Runtime.CompilerServices
1214

1315
open Microsoft.CodeAnalysis
1416
open Microsoft.CodeAnalysis.Completion
@@ -24,15 +26,21 @@ open Microsoft.CodeAnalysis.Text
2426
open Microsoft.VisualStudio.FSharp.LanguageService
2527
open Microsoft.VisualStudio.Text
2628
open Microsoft.VisualStudio.Text.Tagging
29+
open Microsoft.VisualStudio.Shell
30+
open Microsoft.VisualStudio.Shell.Interop
2731

2832
open Microsoft.FSharp.Compiler.Parser
2933
open Microsoft.FSharp.Compiler.Range
3034
open Microsoft.FSharp.Compiler.SourceCodeServices
3135

32-
type internal FSharpCompletionProvider(workspace: Workspace) =
36+
type internal FSharpCompletionProvider(workspace: Workspace, serviceProvider: SVsServiceProvider) =
3337
inherit CompletionProvider()
3438

3539
let completionTriggers = [ '.' ]
40+
let declarationItemsCache = ConditionalWeakTable<string, FSharpDeclarationListItem>()
41+
42+
let xmlMemberIndexService = serviceProvider.GetService(typeof<IVsXMLMemberIndexService>) :?> IVsXMLMemberIndexService
43+
let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder(xmlMemberIndexService, serviceProvider.DTE)
3644

3745
override this.ShouldTriggerCompletion(sourceText: SourceText, caretPosition: int, trigger: CompletionTrigger, _: OptionSet) =
3846
// Skip if we are at the start of a document
@@ -73,8 +81,42 @@ type internal FSharpCompletionProvider(workspace: Workspace) =
7381

7482
| None -> false
7583

76-
override this.ProvideCompletionsAsync(context: Microsoft.CodeAnalysis.Completion.CompletionContext): Task =
77-
Task.CompletedTask
84+
override this.ProvideCompletionsAsync(context: Microsoft.CodeAnalysis.Completion.CompletionContext) =
85+
let computation = async {
86+
match FSharpLanguageService.GetOptions(context.Document.Project.Id) with
87+
| Some(options) ->
88+
let! sourceText = context.Document.GetTextAsync(context.CancellationToken) |> Async.AwaitTask
89+
let! parseResults = FSharpChecker.Instance.ParseFileInProject(context.Document.FilePath, sourceText.ToString(), options)
90+
let! textVersion = context.Document.GetTextVersionAsync(context.CancellationToken) |> Async.AwaitTask
91+
let! checkFileAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, context.Document.FilePath, textVersion.GetHashCode(), sourceText.ToString(), options)
92+
let checkFileResults = match checkFileAnswer with
93+
| FSharpCheckFileAnswer.Aborted -> failwith "Compilation isn't complete yet"
94+
| FSharpCheckFileAnswer.Succeeded(results) -> results
95+
96+
let textLine = sourceText.Lines.GetLineFromPosition(context.Position)
97+
let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based
98+
let qualifyingNames, partialName = QuickParse.GetPartialLongNameEx(textLine.ToString(), context.Position - textLine.Start - 1)
99+
let! declarations = checkFileResults.GetDeclarationListInfo(Some(parseResults), textLineNumber, context.Position, textLine.ToString(), qualifyingNames, partialName)
78100

79-
override this.GetDescriptionAsync(document: Document, item: CompletionItem, cancellationToken: CancellationToken) =
80-
Task.FromResult(CompletionDescription.Empty)
101+
for declarationItem in declarations.Items do
102+
let completionItem = CompletionItem.Create(declarationItem.Name)
103+
declarationItemsCache.Add(completionItem.DisplayText, declarationItem)
104+
context.AddItem(completionItem)
105+
| None -> ()
106+
}
107+
108+
Task.Run(CommonRoslynHelpers.GetTaskAction(computation), context.CancellationToken)
109+
110+
override this.GetDescriptionAsync(_: Document, completionItem: CompletionItem, cancellationToken: CancellationToken): Task<CompletionDescription> =
111+
let computation = async {
112+
let exists, declarationItem = declarationItemsCache.TryGetValue(completionItem.DisplayText)
113+
if exists then
114+
let! description = declarationItem.DescriptionTextAsync
115+
let datatipText = XmlDocumentation.BuildDataTipText(documentationBuilder, description)
116+
return CompletionDescription.FromText(datatipText)
117+
else
118+
return CompletionDescription.Empty
119+
}
120+
121+
Async.StartAsTask(computation, TaskCreationOptions.None, cancellationToken)
122+
.ContinueWith(CommonRoslynHelpers.GetCompletedTaskResult, cancellationToken)

vsintegration/src/FSharp.Editor/CompletionService.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,16 @@ open Microsoft.CodeAnalysis.Text
2424
open Microsoft.VisualStudio.FSharp.LanguageService
2525
open Microsoft.VisualStudio.Text
2626
open Microsoft.VisualStudio.Text.Tagging
27+
open Microsoft.VisualStudio.Shell
2728

2829
open Microsoft.FSharp.Compiler.Parser
2930
open Microsoft.FSharp.Compiler.SourceCodeServices
3031
open Microsoft.FSharp.Compiler.Range
3132

32-
type internal FSharpCompletionService(workspace: Workspace) =
33+
type internal FSharpCompletionService(workspace: Workspace, serviceProvider: SVsServiceProvider) =
3334
inherit CompletionServiceWithProviders(workspace)
3435

35-
let builtInProviders = ImmutableArray.Create<CompletionProvider>(FSharpCompletionProvider(workspace))
36+
let builtInProviders = ImmutableArray.Create<CompletionProvider>(FSharpCompletionProvider(workspace, serviceProvider))
3637
let completionRules = CompletionRules.Default.WithDismissIfEmpty(true).WithDismissIfLastCharacterDeleted(true).WithDefaultEnterKeyRule(EnterKeyRule.Never)
3738

3839
override this.Language = FSharpCommonConstants.FSharpLanguageName

vsintegration/src/FSharp.Editor/CompletionServiceFactory.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,15 @@ open Microsoft.CodeAnalysis.Text
2424
open Microsoft.VisualStudio.FSharp.LanguageService
2525
open Microsoft.VisualStudio.Text
2626
open Microsoft.VisualStudio.Text.Tagging
27+
open Microsoft.VisualStudio.Shell
2728

2829
open Microsoft.FSharp.Compiler.Parser
2930
open Microsoft.FSharp.Compiler.SourceCodeServices
3031
open Microsoft.FSharp.Compiler.Range
3132

3233
[<Shared>]
3334
[<ExportLanguageServiceFactory(typeof<CompletionService>, FSharpCommonConstants.FSharpLanguageName)>]
34-
type internal FSharpCompletionServiceFactory() =
35+
type internal FSharpCompletionServiceFactory [<ImportingConstructor>] (serviceProvider: SVsServiceProvider) =
3536
interface ILanguageServiceFactory with
3637
member this.CreateLanguageService(hostLanguageServices: HostLanguageServices) : ILanguageService =
37-
upcast new FSharpCompletionService(hostLanguageServices.WorkspaceServices.Workspace)
38+
upcast new FSharpCompletionService(hostLanguageServices.WorkspaceServices.Workspace, serviceProvider)

vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ type internal FSharpDocumentDiagnosticAnalyzer() =
3939

4040
Diagnostic.Create(descriptor, Location.Create(filePath, correctedTextSpan , linePositionSpan))
4141

42-
static member GetDiagnostics(filePath: string, sourceText: SourceText, options: FSharpProjectOptions, addSemanticErrors: bool) =
42+
static member GetDiagnostics(filePath: string, sourceText: SourceText, textVersionHash: int, options: FSharpProjectOptions, addSemanticErrors: bool) =
4343
let parseResults = FSharpChecker.Instance.ParseFileInProject(filePath, sourceText.ToString(), options) |> Async.RunSynchronously
4444
let errors =
4545
if addSemanticErrors then
46-
let checkResultsAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, filePath, 0, sourceText.ToString(), options) |> Async.RunSynchronously
46+
let checkResultsAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) |> Async.RunSynchronously
4747
match checkResultsAnswer with
4848
| FSharpCheckFileAnswer.Aborted -> failwith "Compilation isn't complete yet"
4949
| FSharpCheckFileAnswer.Succeeded(results) -> results.Errors
@@ -65,7 +65,8 @@ type internal FSharpDocumentDiagnosticAnalyzer() =
6565
match FSharpLanguageService.GetOptions(document.Project.Id) with
6666
| Some(options) ->
6767
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
68-
return FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document.FilePath, sourceText, options, false)
68+
let! textVersion = document.GetTextVersionAsync(cancellationToken) |> Async.AwaitTask
69+
return FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document.FilePath, sourceText, textVersion.GetHashCode(), options, false)
6970
| None -> return ImmutableArray<Diagnostic>.Empty
7071
}
7172

@@ -78,7 +79,8 @@ type internal FSharpDocumentDiagnosticAnalyzer() =
7879
match FSharpLanguageService.GetOptions(document.Project.Id) with
7980
| Some(options) ->
8081
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
81-
return FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document.FilePath, sourceText, options, true)
82+
let! textVersion = document.GetTextVersionAsync(cancellationToken) |> Async.AwaitTask
83+
return FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document.FilePath, sourceText, textVersion.GetHashCode(), options, true)
8284
| None -> return ImmutableArray<Diagnostic>.Empty
8385
}
8486

vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@
9292
<Reference Include="System" />
9393
<Reference Include="PresentationCore" />
9494
<Reference Include="System.ComponentModel.Composition" />
95+
<Reference Include="EnvDTE.dll" />
96+
<Reference Include="EnvDTE80.dll" />
9597
<Reference Include="Microsoft.VisualStudio.Threading, Version=$(RoslynVSBinariesVersion).0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
9698
<HintPath>$(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Threading.14.1.131\lib\net45\Microsoft.VisualStudio.Threading.dll</HintPath>
9799
</Reference>

0 commit comments

Comments
 (0)