Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check completion context for signature help #1022

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 39 additions & 34 deletions src/FsAutoComplete.Core/SignatureHelp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module FsAutoComplete.SignatureHelp

open System
open FSharp.Compiler.Text
open FsAutoComplete.UntypedAstUtils
open FsToolkit.ErrorHandling
open FsAutoComplete
open FSharp.UMX
Expand Down Expand Up @@ -212,38 +213,42 @@ let getSignatureHelpFor
possibleSessionKind
) =
asyncResult {
let previousNonWhitespaceChar =
let rec loop ch pos =
if Char.IsWhiteSpace ch then
match lines.TryGetPrevChar pos with
| Some (prevPos, prevChar) -> loop prevChar prevPos
| None -> None
else
Some(pos, ch)

match lines.TryGetPrevChar pos with
| Some (prevPos, prevChar) -> loop prevChar prevPos
| None -> None

let! (previousNonWhitespaceCharPos, previousNonWhitespaceChar) =
previousNonWhitespaceChar
|> Result.ofOption (fun _ -> "Couldn't find previous non-whitespace char")

let! charAtPos =
triggerChar
|> Option.orElseWith (fun _ -> lines.TryGetChar pos)
|> Result.ofOption (fun _ -> "Couldn't find a trigger char")

match charAtPos, possibleSessionKind with
// Generally ' ' indicates a function application, but it's also used commonly after a comma in a method call.
// This means that the adjusted position relative to the caret could be a ',' or a '(' or '<',
// which would mean we're already inside of a method call - not a function argument. So we bail if that's the case.
| (' ', _)
| (_, Some FunctionApplication) when
previousNonWhitespaceChar <> ','
&& previousNonWhitespaceChar <> '('
&& previousNonWhitespaceChar <> '<'
->
return! getSignatureHelpForFunctionApplication (tyRes, pos, previousNonWhitespaceCharPos, lines)
| _ -> return! getSignatureHelpForMethod (tyRes, pos, lines, triggerChar)
match Completion.atPos (pos, tyRes.GetParseResults.ParseTree) with
| Completion.Context.StringLiteral -> return None
| Completion.Context.SynType
| Completion.Context.Unknown ->
let previousNonWhitespaceChar =
let rec loop ch pos =
if Char.IsWhiteSpace ch then
match lines.TryGetPrevChar pos with
| Some (prevPos, prevChar) -> loop prevChar prevPos
| None -> None
else
Some(pos, ch)

match lines.TryGetPrevChar pos with
| Some (prevPos, prevChar) -> loop prevChar prevPos
| None -> None

let! (previousNonWhitespaceCharPos, previousNonWhitespaceChar) =
previousNonWhitespaceChar
|> Result.ofOption (fun _ -> "Couldn't find previous non-whitespace char")

let! charAtPos =
triggerChar
|> Option.orElseWith (fun _ -> lines.TryGetChar pos)
|> Result.ofOption (fun _ -> "Couldn't find a trigger char")

match charAtPos, possibleSessionKind with
// Generally ' ' indicates a function application, but it's also used commonly after a comma in a method call.
// This means that the adjusted position relative to the caret could be a ',' or a '(' or '<',
// which would mean we're already inside of a method call - not a function argument. So we bail if that's the case.
| (' ', _)
| (_, Some FunctionApplication) when
previousNonWhitespaceChar <> ','
&& previousNonWhitespaceChar <> '('
&& previousNonWhitespaceChar <> '<'
->
return! getSignatureHelpForFunctionApplication (tyRes, pos, previousNonWhitespaceCharPos, lines)
| _ -> return! getSignatureHelpForMethod (tyRes, pos, lines, triggerChar)
}