Skip to content

Commit 106be3f

Browse files
committed
NoPartialFunctions: workaround for FCS bug
Workaround for bug in FSharp.Compiler.Services that sometimes results in "FSharp.Compiler.Service cannot yet return this kind of pattern match at ..." exception (see ``Regression found when parsing Console/Program_fs`` test case). Issue in F# github repo: [1]. There is a merged PR that should address this bug: [2]. But at the moment latest FSharp.Compiler.Services on nuget (43.8.101) doesn't include that fix. [1] dotnet/fsharp#8854 [2] dotnet/fsharp#16121
1 parent fa6c751 commit 106be3f

File tree

1 file changed

+101
-88
lines changed

1 file changed

+101
-88
lines changed

src/FSharpLint.Core/Rules/Conventions/NoPartialFunctions.fs

Lines changed: 101 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -119,94 +119,107 @@ let rec private tryFindTypedExpression (range: Range) (expression: FSharpExpr) =
119119
if expression.Range = range then
120120
Some expression
121121
else
122-
match expression with
123-
| FSharpExprPatterns.AddressOf(lvalueExpr) ->
124-
tryFindTypedExpression range lvalueExpr
125-
| FSharpExprPatterns.AddressSet(lvalueExpr, rvalueExpr) ->
126-
tryFindTypedExpression range lvalueExpr |> Option.orElse (tryFindTypedExpression range rvalueExpr)
127-
| FSharpExprPatterns.Application(funcExpr, _typeArgs, argExprs) ->
128-
(funcExpr :: argExprs) |> tryFindFirst
129-
| FSharpExprPatterns.Call(objExprOpt, _memberOrFunc, _typeArgs1, _typeArgs2, argExprs) ->
130-
(List.append (Option.toList objExprOpt) argExprs) |> tryFindFirst
131-
| FSharpExprPatterns.Coerce(_targetType, inpExpr) ->
132-
tryFindTypedExpression range inpExpr
133-
| FSharpExprPatterns.FastIntegerForLoop(startExpr, limitExpr, consumeExpr, _isUp, _, _) ->
134-
[ startExpr; limitExpr; consumeExpr ] |> tryFindFirst
135-
| FSharpExprPatterns.ILAsm(_asmCode, _typeArgs, argExprs) ->
136-
tryFindFirst argExprs
137-
| FSharpExprPatterns.ILFieldGet (objExprOpt, _fieldType, _fieldName) ->
138-
objExprOpt |> Option.bind (tryFindTypedExpression range)
139-
| FSharpExprPatterns.ILFieldSet (objExprOpt, _fieldType, _fieldName, valueExpr) ->
140-
objExprOpt |> Option.bind (tryFindTypedExpression range) |> Option.orElse (tryFindTypedExpression range valueExpr)
141-
| FSharpExprPatterns.IfThenElse (guardExpr, thenExpr, elseExpr) ->
142-
[ guardExpr; thenExpr; elseExpr ] |> tryFindFirst
143-
| FSharpExprPatterns.Lambda(_lambdaVar, bodyExpr) ->
144-
tryFindTypedExpression range bodyExpr
145-
| FSharpExprPatterns.Let((_bindingVar, bindingExpr, _), bodyExpr) ->
146-
tryFindTypedExpression range bindingExpr |> Option.orElse (tryFindTypedExpression range bodyExpr)
147-
| FSharpExprPatterns.LetRec(recursiveBindings, bodyExpr) ->
148-
recursiveBindings
149-
|> Seq.choose (fun (_, expr, _) -> tryFindTypedExpression range expr)
150-
|> Seq.tryHead
151-
|> Option.orElse (tryFindTypedExpression range bodyExpr)
152-
| FSharpExprPatterns.NewArray(_arrayType, argExprs) ->
153-
tryFindFirst argExprs
154-
| FSharpExprPatterns.NewDelegate(_delegateType, delegateBodyExpr) ->
155-
tryFindTypedExpression range delegateBodyExpr
156-
| FSharpExprPatterns.NewObject(_objType, _typeArgs, argExprs) ->
157-
tryFindFirst argExprs
158-
| FSharpExprPatterns.NewRecord(_recordType, argExprs) ->
159-
tryFindFirst argExprs
160-
| FSharpExprPatterns.NewAnonRecord(_recordType, argExprs) ->
161-
tryFindFirst argExprs
162-
| FSharpExprPatterns.NewTuple(_tupleType, argExprs) ->
163-
tryFindFirst argExprs
164-
| FSharpExprPatterns.NewUnionCase(_unionType, _unionCase, argExprs) ->
165-
tryFindFirst argExprs
166-
| FSharpExprPatterns.Quote(quotedExpr) ->
167-
tryFindTypedExpression range quotedExpr
168-
| FSharpExprPatterns.FSharpFieldGet(objExprOpt, _recordOrClassType, _fieldInfo) ->
169-
objExprOpt |> Option.bind (tryFindTypedExpression range)
170-
| FSharpExprPatterns.AnonRecordGet(objExpr, _recordOrClassType, _fieldInfo) ->
171-
tryFindTypedExpression range objExpr
172-
| FSharpExprPatterns.FSharpFieldSet(objExprOpt, _recordOrClassType, _fieldInfo, argExpr) ->
173-
objExprOpt |> Option.bind (tryFindTypedExpression range) |> Option.orElse (tryFindTypedExpression range argExpr)
174-
| FSharpExprPatterns.Sequential(firstExpr, secondExpr) ->
175-
tryFindTypedExpression range firstExpr |> Option.orElse (tryFindTypedExpression range secondExpr)
176-
| FSharpExprPatterns.TryFinally(bodyExpr, finalizeExpr, _, _) ->
177-
tryFindTypedExpression range bodyExpr |> Option.orElse (tryFindTypedExpression range finalizeExpr)
178-
| FSharpExprPatterns.TryWith(bodyExpr, _, _, _catchVar, catchExpr, _, _) ->
179-
tryFindTypedExpression range bodyExpr |> Option.orElse (tryFindTypedExpression range catchExpr)
180-
| FSharpExprPatterns.TupleGet(_tupleType, _tupleElemIndex, tupleExpr) ->
181-
tryFindTypedExpression range tupleExpr
182-
| FSharpExprPatterns.DecisionTree(decisionExpr, decisionTargets) ->
183-
tryFindTypedExpression range decisionExpr
184-
|> Option.orElse (decisionTargets |> Seq.choose (fun (_, expr) -> tryFindTypedExpression range expr) |> Seq.tryHead)
185-
| FSharpExprPatterns.DecisionTreeSuccess (_decisionTargetIdx, decisionTargetExprs) ->
186-
tryFindFirst decisionTargetExprs
187-
| FSharpExprPatterns.TypeLambda(_genericParam, bodyExpr) ->
188-
tryFindTypedExpression range bodyExpr
189-
| FSharpExprPatterns.TypeTest(_ty, inpExpr) ->
190-
tryFindTypedExpression range inpExpr
191-
| FSharpExprPatterns.UnionCaseSet(unionExpr, unionType, unionCase, unionCaseField, valueExpr) ->
192-
tryFindTypedExpression range unionExpr |> Option.orElse (tryFindTypedExpression range valueExpr)
193-
| FSharpExprPatterns.UnionCaseGet(unionExpr, _unionType, _unionCase, _unionCaseField) ->
194-
tryFindTypedExpression range unionExpr
195-
| FSharpExprPatterns.UnionCaseTest(unionExpr, _unionType, _unionCase) ->
196-
tryFindTypedExpression range unionExpr
197-
| FSharpExprPatterns.UnionCaseTag(unionExpr, _unionType) ->
198-
tryFindTypedExpression range unionExpr
199-
| FSharpExprPatterns.ObjectExpr(_objType, baseCallExpr, overrides, interfaceImplementations) ->
200-
let interfaceImlps = interfaceImplementations |> List.collect snd
201-
baseCallExpr :: (List.append overrides interfaceImlps |> Seq.cast<FSharpExpr> |> Seq.toList)
202-
|> tryFindFirst
203-
| FSharpExprPatterns.TraitCall(_sourceTypes, _traitName, _typeArgs, _typeInstantiation, _argTypes, argExprs) ->
204-
tryFindFirst argExprs
205-
| FSharpExprPatterns.ValueSet(_valToSet, valueExpr) ->
206-
tryFindTypedExpression range valueExpr
207-
| FSharpExprPatterns.WhileLoop(guardExpr, bodyExpr, _) ->
208-
tryFindTypedExpression range guardExpr |> Option.orElse (tryFindTypedExpression range bodyExpr)
209-
| _ -> None
122+
try
123+
match expression with
124+
| FSharpExprPatterns.AddressOf(lvalueExpr) ->
125+
tryFindTypedExpression range lvalueExpr
126+
| FSharpExprPatterns.AddressSet(lvalueExpr, rvalueExpr) ->
127+
tryFindTypedExpression range lvalueExpr |> Option.orElse (tryFindTypedExpression range rvalueExpr)
128+
| FSharpExprPatterns.Application(funcExpr, _typeArgs, argExprs) ->
129+
(funcExpr :: argExprs) |> tryFindFirst
130+
| FSharpExprPatterns.Call(objExprOpt, _memberOrFunc, _typeArgs1, _typeArgs2, argExprs) ->
131+
(List.append (Option.toList objExprOpt) argExprs) |> tryFindFirst
132+
| FSharpExprPatterns.Coerce(_targetType, inpExpr) ->
133+
tryFindTypedExpression range inpExpr
134+
| FSharpExprPatterns.FastIntegerForLoop(startExpr, limitExpr, consumeExpr, _isUp, _, _) ->
135+
[ startExpr; limitExpr; consumeExpr ] |> tryFindFirst
136+
| FSharpExprPatterns.ILAsm(_asmCode, _typeArgs, argExprs) ->
137+
tryFindFirst argExprs
138+
| FSharpExprPatterns.ILFieldGet (objExprOpt, _fieldType, _fieldName) ->
139+
objExprOpt |> Option.bind (tryFindTypedExpression range)
140+
| FSharpExprPatterns.ILFieldSet (objExprOpt, _fieldType, _fieldName, valueExpr) ->
141+
objExprOpt |> Option.bind (tryFindTypedExpression range) |> Option.orElse (tryFindTypedExpression range valueExpr)
142+
| FSharpExprPatterns.IfThenElse (guardExpr, thenExpr, elseExpr) ->
143+
[ guardExpr; thenExpr; elseExpr ] |> tryFindFirst
144+
| FSharpExprPatterns.Lambda(_lambdaVar, bodyExpr) ->
145+
tryFindTypedExpression range bodyExpr
146+
| FSharpExprPatterns.Let((_bindingVar, bindingExpr, _), bodyExpr) ->
147+
tryFindTypedExpression range bindingExpr |> Option.orElse (tryFindTypedExpression range bodyExpr)
148+
| FSharpExprPatterns.LetRec(recursiveBindings, bodyExpr) ->
149+
recursiveBindings
150+
|> Seq.choose (fun (_, expr, _) -> tryFindTypedExpression range expr)
151+
|> Seq.tryHead
152+
|> Option.orElse (tryFindTypedExpression range bodyExpr)
153+
| FSharpExprPatterns.NewArray(_arrayType, argExprs) ->
154+
tryFindFirst argExprs
155+
| FSharpExprPatterns.NewDelegate(_delegateType, delegateBodyExpr) ->
156+
tryFindTypedExpression range delegateBodyExpr
157+
| FSharpExprPatterns.NewObject(_objType, _typeArgs, argExprs) ->
158+
tryFindFirst argExprs
159+
| FSharpExprPatterns.NewRecord(_recordType, argExprs) ->
160+
tryFindFirst argExprs
161+
| FSharpExprPatterns.NewAnonRecord(_recordType, argExprs) ->
162+
tryFindFirst argExprs
163+
| FSharpExprPatterns.NewTuple(_tupleType, argExprs) ->
164+
tryFindFirst argExprs
165+
| FSharpExprPatterns.NewUnionCase(_unionType, _unionCase, argExprs) ->
166+
tryFindFirst argExprs
167+
| FSharpExprPatterns.Quote(quotedExpr) ->
168+
tryFindTypedExpression range quotedExpr
169+
| FSharpExprPatterns.FSharpFieldGet(objExprOpt, _recordOrClassType, _fieldInfo) ->
170+
objExprOpt |> Option.bind (tryFindTypedExpression range)
171+
| FSharpExprPatterns.AnonRecordGet(objExpr, _recordOrClassType, _fieldInfo) ->
172+
tryFindTypedExpression range objExpr
173+
| FSharpExprPatterns.FSharpFieldSet(objExprOpt, _recordOrClassType, _fieldInfo, argExpr) ->
174+
objExprOpt |> Option.bind (tryFindTypedExpression range) |> Option.orElse (tryFindTypedExpression range argExpr)
175+
| FSharpExprPatterns.Sequential(firstExpr, secondExpr) ->
176+
tryFindTypedExpression range firstExpr |> Option.orElse (tryFindTypedExpression range secondExpr)
177+
| FSharpExprPatterns.TryFinally(bodyExpr, finalizeExpr, _, _) ->
178+
tryFindTypedExpression range bodyExpr |> Option.orElse (tryFindTypedExpression range finalizeExpr)
179+
| FSharpExprPatterns.TryWith(bodyExpr, _, _, _catchVar, catchExpr, _, _) ->
180+
tryFindTypedExpression range bodyExpr |> Option.orElse (tryFindTypedExpression range catchExpr)
181+
| FSharpExprPatterns.TupleGet(_tupleType, _tupleElemIndex, tupleExpr) ->
182+
tryFindTypedExpression range tupleExpr
183+
| FSharpExprPatterns.DecisionTree(decisionExpr, decisionTargets) ->
184+
tryFindTypedExpression range decisionExpr
185+
|> Option.orElse (decisionTargets |> Seq.choose (fun (_, expr) -> tryFindTypedExpression range expr) |> Seq.tryHead)
186+
| FSharpExprPatterns.DecisionTreeSuccess (_decisionTargetIdx, decisionTargetExprs) ->
187+
tryFindFirst decisionTargetExprs
188+
| FSharpExprPatterns.TypeLambda(_genericParam, bodyExpr) ->
189+
tryFindTypedExpression range bodyExpr
190+
| FSharpExprPatterns.TypeTest(_ty, inpExpr) ->
191+
tryFindTypedExpression range inpExpr
192+
| FSharpExprPatterns.UnionCaseSet(unionExpr, unionType, unionCase, unionCaseField, valueExpr) ->
193+
tryFindTypedExpression range unionExpr |> Option.orElse (tryFindTypedExpression range valueExpr)
194+
| FSharpExprPatterns.UnionCaseGet(unionExpr, _unionType, _unionCase, _unionCaseField) ->
195+
tryFindTypedExpression range unionExpr
196+
| FSharpExprPatterns.UnionCaseTest(unionExpr, _unionType, _unionCase) ->
197+
tryFindTypedExpression range unionExpr
198+
| FSharpExprPatterns.UnionCaseTag(unionExpr, _unionType) ->
199+
tryFindTypedExpression range unionExpr
200+
| FSharpExprPatterns.ObjectExpr(_objType, baseCallExpr, overrides, interfaceImplementations) ->
201+
let interfaceImlps = interfaceImplementations |> List.collect snd
202+
baseCallExpr :: (List.append overrides interfaceImlps |> Seq.cast<FSharpExpr> |> Seq.toList)
203+
|> tryFindFirst
204+
| FSharpExprPatterns.TraitCall(_sourceTypes, _traitName, _typeArgs, _typeInstantiation, _argTypes, argExprs) ->
205+
tryFindFirst argExprs
206+
| FSharpExprPatterns.ValueSet(_valToSet, valueExpr) ->
207+
tryFindTypedExpression range valueExpr
208+
| FSharpExprPatterns.WhileLoop(guardExpr, bodyExpr, _) ->
209+
tryFindTypedExpression range guardExpr |> Option.orElse (tryFindTypedExpression range bodyExpr)
210+
| _ -> None
211+
with
212+
| exn ->
213+
// workaround for bug in FSharp.Compiler.Services that sometimes results in
214+
// "FSharp.Compiler.Service cannot yet return this kind of pattern match at ..." exception
215+
// see https://github.com/dotnet/fsharp/issues/8854
216+
// also see https://github.com/ionide/FSharp.Analyzers.SDK/blob/49a5a209455870884888761afd9039bd7bea3a72/src/FSharp.Analyzers.SDK/TASTCollecting.fs#L370
217+
// there is a merged PR that should address this bug: https://github.com/dotnet/fsharp/pull/16121
218+
// but at the time of writing this comment latest FSharp.Compiler.Services on nuget (43.8.101) doesn't include that fix
219+
if exn.Message.Contains "FSharp.Compiler.Service cannot yet return this kind of pattern match at" then
220+
None
221+
else
222+
reraise()
210223

211224
let private getTypedExpressionForRange (checkFile:FSharpCheckFileResults) (range: Range) =
212225
let expressions =

0 commit comments

Comments
 (0)