@@ -21,6 +21,7 @@ open Microsoft.FSharp.Compiler
2121open Microsoft.FSharp .Compiler .Range
2222open Microsoft.FSharp .Compiler .SourceCodeServices
2323open System.Runtime .Caching
24+ open System.Collections .Concurrent
2425
2526type internal FSharpCompletionProvider
2627(
@@ -34,8 +35,9 @@ type internal FSharpCompletionProvider
3435inherit CompletionProvider()
3536
3637static let userOpName = " CompletionProvider"
37- // Save the backing data in a memory cache held in a sliding window
38- static let declarationItemsCache = new MemoryCache( " FSharp.Editor." + userOpName)
38+ // Save the backing data in a cache, we need to save for at least the length of the completion session
39+ // See https://github.com/Microsoft/visualfsharp/issues/4714
40+ static let declarationItemsData = new ConcurrentDictionary< string, FSharpDeclarationListItem>()
3941static let [<Literal>] NameInCodePropName = " NameInCode"
4042static let [<Literal>] FullNamePropName = " FullName"
4143static let [<Literal>] IsExtensionMemberPropName = " IsExtensionMember"
@@ -139,6 +141,7 @@ type internal FSharpCompletionProvider
139141
140142let maxHints = if mruItems.Values.Count= 0 then 0 else Seq.max mruItems.Values
141143
144+ declarationItemsData.Clear()
142145 sortedDeclItems|> Array.iteri( fun number declarationItem ->
143146let glyph = Tokenizer.FSharpGlyphToRoslynGlyph( declarationItem.Glyph, declarationItem.Accessibility)
144147let name =
@@ -184,9 +187,7 @@ type internal FSharpCompletionProvider
184187let completionItem = completionItem.WithSortText( sortText)
185188
186189let key = completionItem.DisplayText
187- let cacheItem = CacheItem( key, declarationItem)
188- let policy = CacheItemPolicy( SlidingExpiration= DefaultTuning.PerDocumentSavedDataSlidingWindow)
189- declarationItemsCache.Set( cacheItem, policy)
190+ declarationItemsData.TryAdd( key, declarationItem) |> ignore
190191 results.Add( completionItem))
191192
192193if results.Count> 0 && not declarations.IsForType&& not declarations.IsError&& List.isEmpty partialName.QualifyingIdentsthen
@@ -212,7 +213,7 @@ type internal FSharpCompletionProvider
212213( documentId, document.FilePath, defines)
213214
214215 FSharpCompletionProvider.ShouldTriggerCompletionAux( sourceText, caretPosition, trigger.Kind, getInfo)
215-
216+
216217override this.ProvideCompletionsAsync ( context : Completion.CompletionContext ) =
217218asyncMaybe {
218219let document = context.Document
@@ -228,13 +229,14 @@ type internal FSharpCompletionProvider
228229let! results =
229230 FSharpCompletionProvider.ProvideCompletionsAsyncAux( checker, sourceText, context.Position, projectOptions,
230231 document.FilePath, textVersion.GetHashCode(), getAllSymbols)
232+
231233 context.AddItems( results)
232234} |> Async.Ignore|> RoslynHelpers.StartAsyncUnitAsTask context.CancellationToken
233235
234236override this.GetDescriptionAsync ( _ : Document , completionItem : Completion.CompletionItem , cancellationToken : CancellationToken ): Task < CompletionDescription > =
235237async {
236- match declarationItemsCache.Get ( completionItem.DisplayText) with
237- | : ? FSharpDeclarationListItem as declarationItem->
238+ match declarationItemsData.TryGetValue ( completionItem.DisplayText) with
239+ | true , declarationItem->
238240let! description = declarationItem.StructuredDescriptionTextAsync
239241let documentation = List()
240242let collector = RoslynHelpers.CollectTaggedText documentation