diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index 8e06873f75e..b526c09a796 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -986,24 +986,32 @@ type internal TypeCheckInfo None /// Suggest name based on type - let SuggestNameBasedOnType g pos ty = - if isNumericType g ty then - CreateCompletionItemForSuggestedPatternName pos "num" - else - match tryTcrefOfAppTy g ty with - | ValueSome tcref when not (tyconRefEq g g.system_Object_tcref tcref) -> - CreateCompletionItemForSuggestedPatternName pos tcref.DisplayName - | _ -> None + let SuggestNameBasedOnType (g: TcGlobals) pos ty = + match stripTyparEqns ty with + | TType_app (tyconRef = tcref) when tcref.IsTypeAbbrev && (tcref.IsLocalRef || not (ccuEq g.fslibCcu tcref.nlr.Ccu)) -> + // Respect user-defined aliases + CreateCompletionItemForSuggestedPatternName pos tcref.DisplayName + | ty -> + if isNumericType g ty then + CreateCompletionItemForSuggestedPatternName pos "num" + else + match tryTcrefOfAppTy g ty with + | ValueSome tcref when not (tyconRefEq g g.system_Object_tcref tcref) -> + CreateCompletionItemForSuggestedPatternName pos tcref.DisplayName + | _ -> None /// Suggest names based on field name and type, add them to the list - let SuggestNameForUnionCaseFieldPattern g caseIdPos fieldPatternPos (uci: UnionCaseInfo) indexOrName completions = + let SuggestNameForUnionCaseFieldPattern g caseIdPos fieldPatternPos (uci: UnionCaseInfo) indexOrName isTheOnlyField completions = let field = match indexOrName with | Choice1Of2 index -> - // Index is None when parentheses were not used, i.e. "| Some v ->" - suggest a name only when the case has a single field match uci.UnionCase.RecdFieldsArray, index with - | [| field |], None -> Some field - | [| _ |], Some _ + | [| field |], None -> + // Index is None when parentheses were not used, i.e. `| Some v ->` - suggest a name only when the case has a single field + Some field + | [| _ |], Some _ when not isTheOnlyField -> + // When completing `| Some (a| , b)`, we're binding the first tuple element, not the sole case field + None | _, None -> None | arr, Some index -> arr |> Array.tryItem index | Choice2Of2 name -> uci.UnionCase.RecdFieldsArray |> Array.tryFind (fun x -> x.DisplayName = name) @@ -1016,7 +1024,7 @@ type internal TypeCheckInfo sResolutions.CapturedNameResolutions |> ResizeArray.tryPick (fun r -> match r.Item with - | Item.Value vref when r.Pos = fieldPatternPos -> Some(stripTyparEqns vref.Type) + | Item.Value vref when r.Pos = fieldPatternPos -> Some vref.Type | _ -> None) |> Option.defaultValue field.FormalType else @@ -1118,7 +1126,7 @@ type internal TypeCheckInfo |> Option.defaultValue [] |> List.append (fields indexOrName isTheOnlyField uci) - Some(SuggestNameForUnionCaseFieldPattern g caseIdRange.End pos uci indexOrName list, r.DisplayEnv, r.Range) + Some(SuggestNameForUnionCaseFieldPattern g caseIdRange.End pos uci indexOrName isTheOnlyField list, r.DisplayEnv, r.Range) | _ -> None) |> Option.orElse declaredItems diff --git a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs index 157331988df..71fb3b0c963 100644 --- a/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs +++ b/vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs @@ -1710,6 +1710,16 @@ fun (Some v) -> () type C = member _.M (Ids (c, o)) = () + + +type MyAlias = int + +type Id2<'a> = Id2 of fff: 'a + +let r: Id2 = Id2 3 + +match r with +| Id2 (a) -> () """ VerifyCompletionList(fileContents, "let x (Ids (c", [ "customerId"; "num" ], []) @@ -1720,7 +1730,9 @@ type C = VerifyCompletionList(fileContents, "fun (Ids (c, o", [ "orderId"; "option" ], []) VerifyCompletionList(fileContents, "fun (Some v", [ "value" ], []) VerifyCompletionList(fileContents, "member _.M (Ids (c", [ "customerId"; "num" ], [ "orderId" ]) - VerifyCompletionList(fileContents, "member _.M (Ids (c, o", [ "orderId"; "option" ], [ "customerId"; "num" ]) + + // Respecting the type alias + VerifyCompletionList(fileContents, "| Id2 (a", [ "fff"; "myAlias" ], [ "num" ]) [] let ``Completion list does not contain suggested names in tuple deconstruction`` () = @@ -1735,7 +1747,9 @@ match Some (1, 2) with VerifyCompletionList(fileContents, "| Some v", [ "value" ], []) VerifyCompletionList(fileContents, "| Some (a", [], [ "value" ]) VerifyCompletionList(fileContents, "| Some (a, b", [], [ "value" ]) - VerifyCompletionList(fileContents, "| Some (c", [], [ "value" ]) + + // Binding the whole tuple here, so the field name should be present + VerifyCompletionList(fileContents, "| Some (c", [ "value" ], []) [] let ``Completion list contains suggested names for union case field pattern based on the name of the generic type's solution`` () =