Skip to content

Commit 4bc46d3

Browse files
committed
Add support for extracting case names from partial active patterns and enhance related tests
1 parent 0579a0a commit 4bc46d3

File tree

2 files changed

+157
-6
lines changed

2 files changed

+157
-6
lines changed

src/FsAutoComplete.Core/Commands.fs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -936,11 +936,30 @@ module Commands =
936936

937937
let symbolNameCore =
938938
match symbol with
939-
| :? FSharpMemberOrFunctionOrValue as mfv when
940-
mfv.IsActivePattern
941-
|| (mfv.DisplayName.StartsWith("(|") && mfv.DisplayName.EndsWith("|)"))
942-
->
943-
mfv.DisplayName.TrimStart('(', '|').TrimEnd(')', '|', '_')
939+
| :? FSharpActivePatternCase as apc ->
940+
// For active pattern cases, use the case name directly
941+
// apc.Name may include bars like "|LetterOrDigit|_|" for partial patterns
942+
// We need to extract just the case name without bars
943+
let name = apc.Name
944+
if name.StartsWith("|") then
945+
// Partial pattern: "|CaseName|_|" -> extract "CaseName"
946+
let parts = name.Split('|') |> Array.filter (fun s -> s <> "" && s <> "_")
947+
if parts.Length > 0 then parts.[0] else name
948+
else
949+
name
950+
| :? FSharpMemberOrFunctionOrValue as mfv when mfv.IsActivePattern ->
951+
// For active pattern functions (the function definition), extract just the case name(s)
952+
// DisplayNameCore is like "|LetterOrDigit|_|" for partial patterns
953+
// For multi-case patterns like "(|Even|Odd|)", we should return the full pattern
954+
let displayName = symbol.DisplayNameCore
955+
if displayName.Contains("|_|") then
956+
// Partial active pattern - extract just the case name(s) without the partial marker
957+
// "|CaseName|_|" -> "CaseName"
958+
let parts = displayName.Split('|') |> Array.filter (fun s -> s <> "" && s <> "_")
959+
if parts.Length > 0 then parts.[0] else displayName
960+
else
961+
// Full active pattern - use DisplayNameCore as-is
962+
displayName
944963
| _ -> symbol.DisplayNameCore
945964

946965
let tryAdjustRanges (text: IFSACSourceText, ranges: seq<Range>) =

test/FsAutoComplete.Tests.Lsp/FindReferencesTests.fs

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,138 @@ let fix (getFileLines: obj) : obj =
743743
744744
return ()
745745
}
746+
"""
747+
testCaseAsync "can get range of partial Active Pattern definition and usages"
748+
<| checkRanges
749+
server
750+
"""
751+
module MyModule =
752+
let (|$D<Pars$0eInt>D$|_|) (s: string) =
753+
match System.Int32.TryParse s with
754+
| true, i -> Some i
755+
| _ -> None
756+
757+
open MyModule
758+
let test input =
759+
match input with
760+
| $<ParseInt>$ i -> printfn "Got %d" i
761+
| _ -> printfn "Not an int"
762+
763+
let test2 input =
764+
match input with
765+
| MyModule.$<ParseInt>$ i -> i
766+
| _ -> 0
767+
"""
768+
testCaseAsync "can get range of partial Active Pattern with nested matches"
769+
<| checkRanges
770+
server
771+
"""
772+
let (|$D<Posi$0tive>D$|_|) n = if n > 0 then Some n else None
773+
let (|Negative|_|) n = if n < 0 then Some n else None
774+
775+
let classify n =
776+
match n with
777+
| $<Positive>$ p ->
778+
match p with
779+
| $<Positive>$ _ -> "still positive"
780+
| _ -> "?"
781+
| Negative _ -> "negative"
782+
| _ -> "zero"
783+
"""
784+
testCaseAsync "can get range of partial Active Pattern used in Or pattern"
785+
<| checkRanges
786+
server
787+
"""
788+
let (|$D<Even$0>D$|_|) n = if n % 2 = 0 then Some() else None
789+
let (|DivisibleBy3|_|) n = if n % 3 = 0 then Some() else None
790+
791+
let test n =
792+
match n with
793+
| $<Even>$ | DivisibleBy3 -> "divisible by 2 or 3"
794+
| _ -> "other"
795+
"""
796+
testCaseAsync "can get range of partial Active Pattern used in And pattern"
797+
<| checkRanges
798+
server
799+
"""
800+
let (|$D<Posi$0tive>D$|_|) n = if n > 0 then Some n else None
801+
let (|LessThan100|_|) n = if n < 100 then Some n else None
802+
803+
let test n =
804+
match n with
805+
| $<Positive>$ _ & LessThan100 _ -> "positive and less than 100"
806+
| _ -> "other"
807+
"""
808+
testCaseAsync "can get range of partial Active Pattern with extracted value"
809+
<| checkRanges
810+
server
811+
"""
812+
let (|$D<RegexMat$0ch>D$|_|) pattern input =
813+
let m = System.Text.RegularExpressions.Regex.Match(input, pattern)
814+
if m.Success then Some m.Value else None
815+
816+
let parseEmail s =
817+
match s with
818+
| $<RegexMatch>$ @"[\w.-]+@[\w.-]+" email -> Some email
819+
| _ -> None
820+
"""
821+
testCaseAsync "can get range of partial Active Pattern in script with local definition"
822+
<| checkRangesScript
823+
server
824+
"""
825+
let (|$D<Trima$0ble>D$|_|) (s: string) =
826+
let trimmed = s.Trim()
827+
if trimmed <> s then Some trimmed else None
828+
829+
let processInput input =
830+
match input with
831+
| $<Trimable>$ trimmed -> printfn "Trimmed: %s" trimmed
832+
| other -> printfn "No trim needed: %s" other
833+
834+
let test () =
835+
match " hello " with
836+
| $<Trimable>$ s -> s
837+
| s -> s
838+
"""
839+
testCaseAsync "can get range of partial Active Pattern in script with multiple usages in same match"
840+
<| checkRangesScript
841+
server
842+
"""
843+
let (|$D<Upp$0er>D$|_|) (c: char) = if System.Char.IsUpper c then Some c else None
844+
let (|Lower|_|) (c: char) = if System.Char.IsLower c then Some c else None
845+
846+
let classifyChar c =
847+
match c with
848+
| $<Upper>$ u -> sprintf "Upper: %c" u
849+
| Lower l -> sprintf "Lower: %c" l
850+
| _ -> "Other"
851+
852+
let testMultiple chars =
853+
chars |> List.map (fun c ->
854+
match c with
855+
| $<Upper>$ _ -> "U"
856+
| Lower _ -> "L"
857+
| _ -> "O")
858+
"""
859+
testCaseAsync "can get range of partial Active Pattern defined in nested module"
860+
<| checkRanges
861+
server
862+
"""
863+
module Outer =
864+
module Inner =
865+
let (|$D<StartsWit$0hA>D$|_|) (s: string) =
866+
if s.StartsWith "A" then Some s else None
867+
868+
open Outer.Inner
869+
let test s =
870+
match s with
871+
| $<StartsWithA>$ v -> v
872+
| _ -> ""
873+
874+
let test2 s =
875+
match s with
876+
| Outer.Inner.$<StartsWithA>$ v -> v
877+
| _ -> ""
746878
""" ])
747879

748880
let private activePatternProjectTests state =
@@ -914,7 +1046,7 @@ let tryFixupRangeTests (sourceTextFactory: ISourceTextFactory) =
9141046
// backticks
9151047
let _ = ($<|``Even``|Odd|>$) 42
9161048
let _ = ($<|``Even``|``Odd``|>$) 42
917-
let _ = (``$<|Even|Odd|``) 42
1049+
let _ = (``$<|Even|Odd|>$``) 42
9181050
9191051
// spaces
9201052
let _ = ($<| Even | Odd |>$) 42

0 commit comments

Comments
 (0)