@@ -92,6 +92,21 @@ module Commands =
9292 let fantomasLogger = LogProvider.getLoggerByName " Fantomas"
9393 let commandsLogger = LogProvider.getLoggerByName " Commands"
9494
95+ /// Extracts the case name(s) from an active pattern name string.
96+ /// For partial patterns like "|CaseName|_|" returns "CaseName"
97+ /// For full patterns like "|Even|Odd|" returns the first case name
98+ let extractActivePatternCaseName ( name : string ) : string =
99+ let parts = name.Split( '|' ) |> Array.filter ( fun s -> s <> " " && s <> " _" )
100+ if parts.Length > 0 then parts.[ 0 ] else name
101+
102+ /// Extracts all case names from an active pattern display name.
103+ /// For "(|ParseInt|_|)" returns ["ParseInt"]
104+ /// For "(|Even|Odd|)" returns ["Even"; "Odd"]
105+ let extractActivePatternCaseNames ( displayName : string ) : string list =
106+ displayName.TrimStart( '|' , '(' ) .TrimEnd( '|' , '_' , ')' ) .Split( '|' )
107+ |> Array.filter ( fun s -> not ( String.IsNullOrWhiteSpace( s)))
108+ |> Array.toList
109+
95110 /// Find case usages for partial active patterns by walking the AST
96111 /// Returns ranges where the case names appear in pattern matches
97112 let findPartialActivePatternCaseUsages ( caseNames : string list ) ( parseResults : FSharpParseFileResults ) : range list =
@@ -140,45 +155,27 @@ module Commands =
140155 }
141156
142157 let rec walkExpr ( expr : SynExpr ) =
143- seq {
144- match expr with
145- | SynExpr.Match( expr = matchExpr; clauses = clauses) ->
146- // Walk the discriminator expression
147- yield ! walkExpr matchExpr
148-
158+ let walkMatchClauses clauses =
159+ seq {
149160 for clause in clauses do
150161 match clause with
151162 | SynMatchClause( pat = pat; resultExpr = resultExpr) ->
152163 yield ! walkPat pat
153- // Walk the result expression to find nested matches
154164 yield ! walkExpr resultExpr
165+ }
166+
167+ seq {
168+ match expr with
169+ | SynExpr.Match( expr = matchExpr; clauses = clauses) ->
170+ yield ! walkExpr matchExpr
171+ yield ! walkMatchClauses clauses
155172 | SynExpr.MatchBang( expr = matchExpr; clauses = clauses) ->
156- // Walk the discriminator expression
157173 yield ! walkExpr matchExpr
158-
159- for clause in clauses do
160- match clause with
161- | SynMatchClause( pat = pat; resultExpr = resultExpr) ->
162- yield ! walkPat pat
163- // Walk the result expression to find nested matches
164- yield ! walkExpr resultExpr
174+ yield ! walkMatchClauses clauses
165175 | SynExpr.TryWith( tryExpr = tryExpr; withCases = clauses) ->
166- // Walk the try expression
167176 yield ! walkExpr tryExpr
168-
169- for clause in clauses do
170- match clause with
171- | SynMatchClause( pat = pat; resultExpr = resultExpr) ->
172- yield ! walkPat pat
173- // Walk the result expression to find nested matches
174- yield ! walkExpr resultExpr
175- | SynExpr.MatchLambda( matchClauses = clauses) ->
176- for clause in clauses do
177- match clause with
178- | SynMatchClause( pat = pat; resultExpr = resultExpr) ->
179- yield ! walkPat pat
180- // Walk the result expression to find nested matches
181- yield ! walkExpr resultExpr
177+ yield ! walkMatchClauses clauses
178+ | SynExpr.MatchLambda( matchClauses = clauses) -> yield ! walkMatchClauses clauses
182179 | SynExpr.Lambda( args = args; body = body) ->
183180 match args with
184181 | SynSimplePats.SimplePats( pats = pats) ->
@@ -937,30 +934,20 @@ module Commands =
937934 let symbolNameCore =
938935 match symbol with
939936 | : ? FSharpActivePatternCase as apc ->
940- // For active pattern cases, use the case name directly
937+ // For active pattern cases, extract just the case name without bars
941938 // 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-
945- if name.StartsWith( " |" ) then
946- // Partial pattern: "|CaseName|_|" -> extract "CaseName"
947- let parts = name.Split( '|' ) |> Array.filter ( fun s -> s <> " " && s <> " _" )
948- if parts.Length > 0 then parts.[ 0 ] else name
939+ if apc.Name.StartsWith( " |" ) then
940+ extractActivePatternCaseName apc.Name
949941 else
950- name
942+ apc.Name
951943 | : ? FSharpMemberOrFunctionOrValue as mfv when mfv .IsActivePattern ->
952- // For active pattern functions (the function definition), extract just the case name(s)
953- // DisplayNameCore is like "|LetterOrDigit|_|" for partial patterns
954- // For multi-case patterns like "(|Even|Odd|)", we should return the full pattern
944+ // For active pattern functions, extract just the case name for partial patterns
945+ // For full patterns like "(|Even|Odd|)", use DisplayNameCore as-is
955946 let displayName = symbol.DisplayNameCore
956947
957948 if displayName.Contains( " |_|" ) then
958- // Partial active pattern - extract just the case name(s) without the partial marker
959- // "|CaseName|_|" -> "CaseName"
960- let parts = displayName.Split( '|' ) |> Array.filter ( fun s -> s <> " " && s <> " _" )
961- if parts.Length > 0 then parts.[ 0 ] else displayName
949+ extractActivePatternCaseName displayName
962950 else
963- // Full active pattern - use DisplayNameCore as-is
964951 displayName
965952 | _ -> symbol.DisplayNameCore
966953
@@ -1042,11 +1029,7 @@ module Commands =
10421029 baseFiltered, []
10431030 else
10441031 // For partial patterns, find case usages by walking the AST
1045- // Extract case names from the pattern (e.g., "|ParseInt|_|" -> ["ParseInt"])
1046- let caseNames =
1047- patternDisplayName.TrimStart( '|' , '(' ). TrimEnd( '|' , '_' , ')' ). Split( '|' )
1048- |> Array.filter ( fun s -> not ( String.IsNullOrWhiteSpace( s)))
1049- |> Array.toList
1032+ let caseNames = extractActivePatternCaseNames patternDisplayName
10501033
10511034 let caseUsageRanges =
10521035 findPartialActivePatternCaseUsages caseNames tyRes.GetParseResults
0 commit comments