@@ -36,19 +36,19 @@ open Microsoft.FSharp.Compiler.SourceCodeServices
3636type internal FSharpCompletionProvider ( workspace : Workspace , serviceProvider : SVsServiceProvider ) =
3737 inherit CompletionProvider()
3838
39- let completionTriggers = [ '.' ]
40- let declarationItemsCache = ConditionalWeakTable< string, FSharpDeclarationListItem>()
39+ static let completionTriggers = [ '.' ]
40+ static let declarationItemsCache = ConditionalWeakTable< string, FSharpDeclarationListItem>()
4141
4242 let xmlMemberIndexService = serviceProvider.GetService( typeof< IVsXMLMemberIndexService>) :?> IVsXMLMemberIndexService
4343 let documentationBuilder = XmlDocumentation.CreateDocumentationBuilder( xmlMemberIndexService, serviceProvider.DTE)
4444
45- override this.ShouldTriggerCompletion ( sourceText : SourceText , caretPosition : int , trigger : CompletionTrigger , _ : OptionSet ) =
45+ static member ShouldTriggerCompletionAux ( sourceText : SourceText , caretPosition : int , trigger : CompletionTriggerKind , filePath : string , defines : string list ) =
4646 // Skip if we are at the start of a document
4747 if caretPosition = 0 then
4848 false
4949
5050 // Skip if it was triggered by an operation other than insertion
51- else if not ( trigger.Kind = CompletionTriggerKind.Insertion) then
51+ else if not ( trigger = CompletionTriggerKind.Insertion) then
5252 false
5353
5454 // Skip if we are not on a completion trigger
@@ -57,51 +57,62 @@ type internal FSharpCompletionProvider(workspace: Workspace, serviceProvider: SV
5757
5858 // Trigger completion if we are on a valid classification type
5959 else
60- let documentId = workspace.GetDocumentIdInCurrentContext( sourceText.Container)
61- let document = workspace.CurrentSolution.GetDocument( documentId)
62-
63- match FSharpLanguageService.GetOptions( document.Project.Id) with
64- | Some( options) ->
65-
66- let triggerPosition = caretPosition - 1
67- let textLine = sourceText.Lines.GetLineFromPosition( triggerPosition)
68- let defines = CompilerEnvironment.GetCompilationDefinesForEditing( document.Name, options.OtherOptions |> Seq.toList)
69- let classifiedSpanOption =
70- FSharpColorizationService.GetColorizationData( sourceText, textLine.Span, Some( document.FilePath), defines, CancellationToken.None)
71- |> Seq.tryFind( fun classifiedSpan -> classifiedSpan.TextSpan.Contains( triggerPosition))
72-
73- match classifiedSpanOption with
74- | None -> false
75- | Some( classifiedSpan) ->
76- match classifiedSpan.ClassificationType with
77- | ClassificationTypeNames.Comment -> false
78- | ClassificationTypeNames.StringLiteral -> false
79- | ClassificationTypeNames.ExcludedCode -> false
80- | _ -> true // anything else is a valid classification type
60+ let triggerPosition = caretPosition - 1
61+ let textLine = sourceText.Lines.GetLineFromPosition( triggerPosition)
62+ let classifiedSpanOption =
63+ FSharpColorizationService.GetColorizationData( sourceText, textLine.Span, Some( filePath), defines, CancellationToken.None)
64+ |> Seq.tryFind( fun classifiedSpan -> classifiedSpan.TextSpan.Contains( triggerPosition))
8165
66+ match classifiedSpanOption with
8267 | None -> false
68+ | Some( classifiedSpan) ->
69+ match classifiedSpan.ClassificationType with
70+ | ClassificationTypeNames.Comment -> false
71+ | ClassificationTypeNames.StringLiteral -> false
72+ | ClassificationTypeNames.ExcludedCode -> false
73+ | _ -> true // anything else is a valid classification type
74+
75+ static member ProvideCompletionsAsyncAux ( sourceText : SourceText , caretPosition : int , options : FSharpProjectOptions , filePath : string , textVersionHash : int ) = async {
76+ let! parseResults = FSharpChecker.Instance.ParseFileInProject( filePath, sourceText.ToString(), options)
77+ let! checkFileAnswer = FSharpChecker.Instance.CheckFileInProject( parseResults, filePath, textVersionHash, sourceText.ToString(), options)
78+ let checkFileResults = match checkFileAnswer with
79+ | FSharpCheckFileAnswer.Aborted -> failwith " Compilation isn't complete yet"
80+ | FSharpCheckFileAnswer.Succeeded( results) -> results
81+
82+ let textLine = sourceText.Lines.GetLineFromPosition( caretPosition)
83+ let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based
84+ let qualifyingNames , partialName = QuickParse.GetPartialLongNameEx( textLine.ToString(), caretPosition - textLine.Start - 1 )
85+ let! declarations = checkFileResults.GetDeclarationListInfo( Some( parseResults), textLineNumber, caretPosition, textLine.ToString(), qualifyingNames, partialName)
86+
87+ let results = List< CompletionItem>()
88+
89+ for declarationItem in declarations.Items do
90+ let completionItem = CompletionItem.Create( declarationItem.Name)
91+ declarationItemsCache.Add( completionItem.DisplayText, declarationItem)
92+ results.Add( completionItem)
93+
94+ return results
95+ }
96+
97+
98+ override this.ShouldTriggerCompletion ( sourceText : SourceText , caretPosition : int , trigger : CompletionTrigger , _ : OptionSet ) =
99+ let documentId = workspace.GetDocumentIdInCurrentContext( sourceText.Container)
100+ let document = workspace.CurrentSolution.GetDocument( documentId)
101+
102+ match FSharpLanguageService.GetOptions( document.Project.Id) with
103+ | None -> false
104+ | Some( options) ->
105+ let defines = CompilerEnvironment.GetCompilationDefinesForEditing( document.Name, options.OtherOptions |> Seq.toList)
106+ FSharpCompletionProvider.ShouldTriggerCompletionAux( sourceText, caretPosition, trigger.Kind, document.FilePath, defines)
83107
84108 override this.ProvideCompletionsAsync ( context : Microsoft.CodeAnalysis.Completion.CompletionContext ) =
85109 let computation = async {
86110 match FSharpLanguageService.GetOptions( context.Document.Project.Id) with
87111 | Some( options) ->
88112 let! sourceText = context.Document.GetTextAsync( context.CancellationToken) |> Async.AwaitTask
89- let! parseResults = FSharpChecker.Instance.ParseFileInProject( context.Document.FilePath, sourceText.ToString(), options)
90113 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)
100-
101- for declarationItem in declarations.Items do
102- let completionItem = CompletionItem.Create( declarationItem.Name)
103- declarationItemsCache.Add( completionItem.DisplayText, declarationItem)
104- context.AddItem( completionItem)
114+ let! results = FSharpCompletionProvider.ProvideCompletionsAsyncAux( sourceText, context.Position, options, context.Document.FilePath, textVersion.GetHashCode())
115+ context.AddItems( results)
105116 | None -> ()
106117 }
107118
0 commit comments