Skip to content
This repository was archived by the owner on Dec 23, 2024. It is now read-only.

Commit cdf8db6

Browse files
authored
Show keyword descriptions in completion + refactor (dotnet#9164)
* Completion provider refactor * Actually show keyword descriptions in tooltips for completion * Get rid of unnecessary property * Make the keyword completion list static again * Just do it in the CompletionProvider
1 parent 0451680 commit cdf8db6

File tree

4 files changed

+45
-31
lines changed

4 files changed

+45
-31
lines changed

Completion/CompletionProvider.fs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,21 @@ type internal FSharpCompletionProvider
4141
static let [<Literal>] FullNamePropName = "FullName"
4242
static let [<Literal>] IsExtensionMemberPropName = "IsExtensionMember"
4343
static let [<Literal>] NamespaceToOpenPropName = "NamespaceToOpen"
44-
static let [<Literal>] IsKeywordPropName = "IsKeyword"
4544
static let [<Literal>] IndexPropName = "Index"
45+
static let [<Literal>] KeywordDescription = "KeywordDescription"
4646

4747
static let keywordCompletionItems =
4848
Keywords.KeywordsWithDescription
4949
|> List.filter (fun (keyword, _) -> not (PrettyNaming.IsOperatorName keyword))
5050
|> List.sortBy (fun (keyword, _) -> keyword)
5151
|> List.mapi (fun n (keyword, description) ->
52-
FSharpCommonCompletionItem.Create(keyword, null, CompletionItemRules.Default, Nullable Glyph.Keyword, sortText = sprintf "%06d" (1000000 + n))
53-
.AddProperty("description", description)
54-
.AddProperty(IsKeywordPropName, ""))
52+
FSharpCommonCompletionItem.Create(
53+
displayText = keyword,
54+
displayTextSuffix = "",
55+
rules = CompletionItemRules.Default,
56+
glyph = Nullable Glyph.Keyword,
57+
sortText = sprintf "%06d" (1000000 + n))
58+
.AddProperty(KeywordDescription, description))
5559

5660
let checker = checkerProvider.Checker
5761

@@ -183,22 +187,23 @@ type internal FSharpCompletionProvider
183187
let completionItem = completionItem.WithSortText(sortText)
184188
results.Add(completionItem))
185189

190+
186191
if results.Count > 0 && not declarations.IsForType && not declarations.IsError && List.isEmpty partialName.QualifyingIdents then
187192
let lineStr = textLines.[caretLinePos.Line].ToString()
188-
193+
189194
let completionContext =
190195
parseResults.ParseTree
191196
|> Option.bind (fun parseTree ->
192197
UntypedParseImpl.TryGetCompletionContext(Pos.fromZ caretLinePos.Line caretLinePos.Character, parseTree, lineStr))
193-
198+
194199
match completionContext with
195200
| None -> results.AddRange(keywordCompletionItems)
196201
| _ -> ()
197202

198203
return results
199204
}
200205

201-
override this.ShouldTriggerCompletion(sourceText: SourceText, caretPosition: int, trigger: CompletionTrigger, _: OptionSet) =
206+
override _.ShouldTriggerCompletion(sourceText: SourceText, caretPosition: int, trigger: CompletionTrigger, _: OptionSet) =
202207
use _logBlock = Logger.LogBlock LogEditorFunctionId.Completion_ShouldTrigger
203208

204209
let getInfo() =
@@ -209,7 +214,7 @@ type internal FSharpCompletionProvider
209214

210215
FSharpCompletionProvider.ShouldTriggerCompletionAux(sourceText, caretPosition, trigger.Kind, getInfo, settings.IntelliSense)
211216

212-
override this.ProvideCompletionsAsync(context: Completion.CompletionContext) =
217+
override _.ProvideCompletionsAsync(context: Completion.CompletionContext) =
213218
asyncMaybe {
214219
use _logBlock = Logger.LogBlockMessage context.Document.Name LogEditorFunctionId.Completion_ProvideCompletionsAsync
215220

@@ -230,7 +235,7 @@ type internal FSharpCompletionProvider
230235
context.AddItems(results)
231236
} |> Async.Ignore |> RoslynHelpers.StartAsyncUnitAsTask context.CancellationToken
232237

233-
override this.GetDescriptionAsync(document: Document, completionItem: Completion.CompletionItem, cancellationToken: CancellationToken): Task<CompletionDescription> =
238+
override _.GetDescriptionAsync(document: Document, completionItem: Completion.CompletionItem, cancellationToken: CancellationToken): Task<CompletionDescription> =
234239
async {
235240
use _logBlock = Logger.LogBlockMessage document.Name LogEditorFunctionId.Completion_GetDescriptionAsync
236241
match completionItem.Properties.TryGetValue IndexPropName with
@@ -244,13 +249,18 @@ type internal FSharpCompletionProvider
244249
// mix main description and xmldoc by using one collector
245250
XmlDocumentation.BuildDataTipText(documentationBuilder, collector, collector, collector, collector, collector, description)
246251
return CompletionDescription.Create(documentation.ToImmutableArray())
247-
else
252+
else
253+
return CompletionDescription.Empty
254+
| _ ->
255+
// Try keyword descriptions if they exist
256+
match completionItem.Properties.TryGetValue KeywordDescription with
257+
| true, keywordDescription ->
258+
return CompletionDescription.FromText(keywordDescription)
259+
| false, _ ->
248260
return CompletionDescription.Empty
249-
| _ ->
250-
return CompletionDescription.Empty
251261
} |> RoslynHelpers.StartAsyncAsTask cancellationToken
252262

253-
override this.GetChangeAsync(document, item, _, cancellationToken) : Task<CompletionChange> =
263+
override _.GetChangeAsync(document, item, _, cancellationToken) : Task<CompletionChange> =
254264
async {
255265
use _logBlock = Logger.LogBlockMessage document.Name LogEditorFunctionId.Completion_GetChangeAsync
256266

@@ -259,9 +269,8 @@ type internal FSharpCompletionProvider
259269
| true, x -> Some x
260270
| _ -> None
261271

262-
// do not add extension members, keywords and not yet resolved symbols to the MRU list
263-
if not (item.Properties.ContainsKey NamespaceToOpenPropName) && not (item.Properties.ContainsKey IsExtensionMemberPropName) &&
264-
not (item.Properties.ContainsKey IsKeywordPropName) then
272+
// do not add extension members and unresolved symbols to the MRU list
273+
if not (item.Properties.ContainsKey NamespaceToOpenPropName) && not (item.Properties.ContainsKey IsExtensionMemberPropName) then
265274
match fullName with
266275
| Some fullName ->
267276
match mruItems.TryGetValue fullName with

Completion/CompletionService.fs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,11 @@ type internal FSharpCompletionService
2727
let builtInProviders =
2828
ImmutableArray.Create<CompletionProvider>(
2929
FSharpCompletionProvider(workspace, serviceProvider, checkerProvider, projectInfoManager, assemblyContentProvider),
30-
FSharpCommonCompletionProvider.Create(
31-
HashDirectiveCompletionProvider(workspace, projectInfoManager,
32-
[ Completion.Create("""\s*#load\s+(@?"*(?<literal>"[^"]*"?))""", [".fs"; ".fsx"], useIncludeDirectives = true)
33-
Completion.Create("""\s*#r\s+(@?"*(?<literal>"[^"]*"?))""", [".dll"; ".exe"], useIncludeDirectives = true)
34-
Completion.Create("""\s*#I\s+(@?"*(?<literal>"[^"]*"?))""", ["\x00"], useIncludeDirectives = false) ])))
30+
FSharpCommonCompletionProvider.Create(HashDirectiveCompletionProvider.Create(workspace, projectInfoManager)))
3531

36-
override this.Language = FSharpConstants.FSharpLanguageName
37-
override this.GetBuiltInProviders() = builtInProviders
38-
override this.GetRules() =
32+
override _.Language = FSharpConstants.FSharpLanguageName
33+
override _.GetBuiltInProviders() = builtInProviders
34+
override _.GetRules() =
3935
let enterKeyRule =
4036
match settings.IntelliSense.EnterKeySetting with
4137
| NeverNewline -> EnterKeyRule.Never
@@ -59,7 +55,7 @@ type internal FSharpCompletionServiceFactory
5955
settings: EditorOptions
6056
) =
6157
interface ILanguageServiceFactory with
62-
member this.CreateLanguageService(hostLanguageServices: HostLanguageServices) : ILanguageService =
58+
member _.CreateLanguageService(hostLanguageServices: HostLanguageServices) : ILanguageService =
6359
upcast new FSharpCompletionService(hostLanguageServices.WorkspaceServices.Workspace, serviceProvider, checkerProvider, projectInfoManager, assemblyContentProvider, settings)
6460

6561

Completion/FileSystemCompletion.fs renamed to Completion/HashDirectiveCompletionProvider.fs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ open Microsoft.CodeAnalysis.Text
1414
open Microsoft.CodeAnalysis.Classification
1515
open Microsoft.CodeAnalysis.ExternalAccess.FSharp.Completion
1616

17-
type internal Completion =
17+
type internal HashCompletion =
1818
{ DirectiveRegex: Regex
1919
AllowableExtensions: string list
2020
UseIncludeDirectives: bool }
@@ -23,7 +23,7 @@ type internal Completion =
2323
AllowableExtensions = allowableExtensions
2424
UseIncludeDirectives = useIncludeDirectives }
2525

26-
type internal HashDirectiveCompletionProvider(workspace: Workspace, projectInfoManager: FSharpProjectOptionsManager, completions: Completion list) =
26+
type internal HashDirectiveCompletionProvider(workspace: Workspace, projectInfoManager: FSharpProjectOptionsManager, completions: HashCompletion list) =
2727

2828
let [<Literal>] NetworkPath = "\\\\"
2929
let commitRules = ImmutableArray.Create(CharacterSetModificationRule.Create(CharacterSetModificationKind.Replace, '"', '\\', ',', '/'))
@@ -82,9 +82,18 @@ type internal HashDirectiveCompletionProvider(workspace: Workspace, projectInfoM
8282
)
8383
|> Seq.toList
8484

85+
static member Create(workspace: Workspace, projectInfoManager: FSharpProjectOptionsManager) =
86+
let completions =
87+
[
88+
HashCompletion.Create("""\s*#load\s+(@?"*(?<literal>"[^"]*"?))""", [ ".fs"; ".fsx" ], useIncludeDirectives = true)
89+
HashCompletion.Create("""\s*#r\s+(@?"*(?<literal>"[^"]*"?))""", [ ".dll"; ".exe" ], useIncludeDirectives = true)
90+
HashCompletion.Create("""\s*#I\s+(@?"*(?<literal>"[^"]*"?))""", [ "\x00" ], useIncludeDirectives = false)
91+
]
92+
HashDirectiveCompletionProvider(workspace, projectInfoManager, completions)
93+
8594
interface IFSharpCommonCompletionProvider with
8695

87-
member this.ProvideCompletionsAsync(context) =
96+
member _.ProvideCompletionsAsync(context) =
8897
asyncMaybe {
8998
let document = context.Document
9099
let position = context.Position
@@ -137,7 +146,7 @@ type internal HashDirectiveCompletionProvider(workspace: Workspace, projectInfoM
137146
|> Async.Ignore
138147
|> RoslynHelpers.StartAsyncUnitAsTask context.CancellationToken
139148

140-
member __.IsInsertionTrigger(text, position, _) =
149+
member _.IsInsertionTrigger(text, position, _) =
141150
// Bring up completion when the user types a quote (i.e.: #r "), or if they type a slash
142151
// path separator character, or if they type a comma (#r "foo,version...").
143152
// Also, if they're starting a word. i.e. #r "c:\W
@@ -147,7 +156,7 @@ type internal HashDirectiveCompletionProvider(workspace: Workspace, projectInfoM
147156
FSharpCommonCompletionUtilities.IsStartingNewWord(text, position, (fun x -> Char.IsLetter x), (fun x -> Char.IsLetterOrDigit x))
148157
isTriggerChar && isInStringLiteral(text, position)
149158

150-
member __.GetTextChangeAsync(baseGetTextChangeAsync, selectedItem, ch, cancellationToken) =
159+
member _.GetTextChangeAsync(baseGetTextChangeAsync, selectedItem, ch, cancellationToken) =
151160
// When we commit "\\" when the user types \ we have to adjust for the fact that the
152161
// controller will automatically append \ after we commit. Because of that, we don't
153162
// want to actually commit "\\" as we'll end up with "\\\". So instead we just commit

FSharp.Editor.fsproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
<Compile Include="Completion\CompletionUtils.fs" />
6969
<Compile Include="Completion\CompletionProvider.fs" />
7070
<Compile Include="Completion\PathCompletionUtilities.fs" />
71-
<Compile Include="Completion\FileSystemCompletion.fs" />
71+
<Compile Include="Completion\HashDirectiveCompletionProvider.fs" />
7272
<Compile Include="Completion\CompletionService.fs" />
7373
<Compile Include="Completion\SignatureHelp.fs" />
7474
<Compile Include="InlineRename\InlineRenameService.fs" />

0 commit comments

Comments
 (0)