@@ -800,6 +800,28 @@ type internal TypeCheckInfo
800800 | Item.Types (_, ty :: _) when isInterfaceTy g ty -> true
801801 | _ -> false
802802
803+ /// Is the item suitable for completion in a pattern
804+ let IsPatternCandidate ( item : CompletionItem ) =
805+ match item.Item with
806+ | Item.Value v -> v.LiteralValue.IsSome
807+ | Item.ILField field -> field.LiteralValue.IsSome
808+ | Item.ActivePatternCase _
809+ | Item.ExnCase _
810+ | Item.ModuleOrNamespaces _
811+ | Item.Types _
812+ | Item.UnionCase _ -> true
813+ | _ -> false
814+
815+ /// Is the item suitable for completion in a type application or type annotation
816+ let IsTypeCandidate ( item : CompletionItem ) =
817+ match item.Item with
818+ | Item.ModuleOrNamespaces _
819+ | Item.Types _
820+ | Item.TypeVar _
821+ | Item.UnqualifiedType _
822+ | Item.ExnCase _ -> true
823+ | _ -> false
824+
803825 /// Return only items with the specified name, modulo "Attribute" for type completions
804826 let FilterDeclItemsByResidue ( getItem : 'a -> Item ) residue ( items : 'a list ) =
805827 let attributedResidue = residue + " Attribute"
@@ -939,6 +961,10 @@ type internal TypeCheckInfo
939961 Unresolved = None
940962 }
941963
964+ let getItem ( x : ItemWithInst ) = x.Item
965+
966+ let getItem2 ( x : CompletionItem ) = x.Item
967+
942968 /// Checks whether the suggested name is unused.
943969 /// In the future we could use an increasing numeric suffix for conflict resolution
944970 let CreateCompletionItemForSuggestedPatternName ( pos : pos ) name =
@@ -1044,7 +1070,7 @@ type internal TypeCheckInfo
10441070 |> List.map ( fun ( name , overloads ) ->
10451071 Item.MethodGroup( name, overloads, None)
10461072 |> ItemWithNoInst
1047- |> CompletionItem ValueNone ValueNone )
1073+ |> DefaultCompletionItem )
10481074
10491075 Some( overridableMethods, nenv.DisplayEnv, m)
10501076 | _ -> None)
@@ -1063,12 +1089,77 @@ type internal TypeCheckInfo
10631089 else
10641090 Item.UnionCaseField( uci, index)
10651091 |> ItemWithNoInst
1066- |> CompletionItem ValueNone ValueNone
1092+ |> DefaultCompletionItem
10671093 |> Some)
10681094 |> Some
10691095 | _ -> None)
10701096
1071- let getItem ( x : ItemWithInst ) = x.Item
1097+ let GetCompletionsForUnionCaseField pos indexOrName caseIdRange isTheOnlyField declaredItems =
1098+ let declaredItems =
1099+ declaredItems
1100+ |> Option.bind ( FilterRelevantItemsBy getItem2 None IsPatternCandidate)
1101+
1102+ // When the user types `fun (Case (x| )) ->`, we do not yet know whether the intention is to use positional or named arguments,
1103+ // so let's show options for both.
1104+ let fields indexOrName isTheOnlyField ( uci : UnionCaseInfo ) =
1105+ match indexOrName, isTheOnlyField with
1106+ | Choice1Of2 ( Some 0 ), true ->
1107+ uci.UnionCase.RecdFields
1108+ |> List.mapi ( fun index _ -> Item.UnionCaseField( uci, index) |> ItemWithNoInst |> DefaultCompletionItem)
1109+ | _ -> []
1110+
1111+ sResolutions.CapturedNameResolutions
1112+ |> ResizeArray.tryPick ( fun r ->
1113+ match r.Item with
1114+ | Item.UnionCase ( uci, _) when equals r.Range caseIdRange ->
1115+ let list =
1116+ declaredItems
1117+ |> Option.map p13
1118+ |> Option.defaultValue []
1119+ |> List.append ( fields indexOrName isTheOnlyField uci)
1120+
1121+ Some( SuggestNameForUnionCaseFieldPattern g caseIdRange.End pos uci indexOrName list, r.DisplayEnv, r.Range)
1122+ | _ -> None)
1123+ |> Option.orElse declaredItems
1124+
1125+ let GetCompletionsForRecordField pos referencedFields declaredItems =
1126+ declaredItems
1127+ |> Option.map ( fun ( items : CompletionItem list , denv , range ) ->
1128+ let fields =
1129+ // Try to find a name resolution for any of the referenced fields, and through it access all available fields of the record
1130+ referencedFields
1131+ |> List.tryPick ( fun ( _ , fieldRange ) ->
1132+ sResolutions.CapturedNameResolutions
1133+ |> ResizeArray.tryPick ( fun cnr ->
1134+ match cnr.Item with
1135+ | Item.RecdField info when equals cnr.Range fieldRange ->
1136+ info.TyconRef.AllFieldAsRefList
1137+ |> List.choose ( fun field ->
1138+ if
1139+ referencedFields
1140+ |> List.exists ( fun ( fieldName , _ ) -> fieldName = field.DisplayName)
1141+ then
1142+ None
1143+ else
1144+ FreshenRecdFieldRef ncenv field.Range field |> Item.RecdField |> Some)
1145+ |> Some
1146+ | _ -> None))
1147+ |> Option.defaultWith ( fun () ->
1148+ // Fall back to showing all record field names in scope
1149+ let ( nenv , _ ), _ = GetBestEnvForPos pos
1150+ getRecordFieldsInScope nenv)
1151+ |> List.map ( ItemWithNoInst >> DefaultCompletionItem)
1152+
1153+ let items =
1154+ items
1155+ |> List.filter ( fun item ->
1156+ match item.Item with
1157+ | Item.ModuleOrNamespaces _ -> true
1158+ | Item.Types (_, ty :: _) -> isRecdTy g ty
1159+ | _ -> false )
1160+ |> List.append fields
1161+
1162+ items, denv, range)
10721163
10731164 let GetDeclaredItems
10741165 (
@@ -1316,6 +1407,22 @@ type internal TypeCheckInfo
13161407 | atStart when atStart = 0 -> 0
13171408 | otherwise -> otherwise - 1
13181409
1410+ let getDeclaredItemsNotInRangeOpWithAllSymbols () =
1411+ GetDeclaredItems(
1412+ parseResultsOpt,
1413+ lineStr,
1414+ origLongIdentOpt,
1415+ colAtEndOfNamesAndResidue,
1416+ residueOpt,
1417+ lastDotPos,
1418+ line,
1419+ loc,
1420+ filterCtors,
1421+ resolveOverloads,
1422+ false ,
1423+ getAllSymbols
1424+ )
1425+
13191426 let pos = mkPos line colAtEndOfNamesAndResidue
13201427
13211428 // Look for a "special" completion context
@@ -1445,21 +1552,7 @@ type internal TypeCheckInfo
14451552 | Some ( CompletionContext.ParameterList ( endPos, fields)) ->
14461553 let results = GetNamedParametersAndSettableFields endPos
14471554
1448- let declaredItems =
1449- GetDeclaredItems(
1450- parseResultsOpt,
1451- lineStr,
1452- origLongIdentOpt,
1453- colAtEndOfNamesAndResidue,
1454- residueOpt,
1455- lastDotPos,
1456- line,
1457- loc,
1458- filterCtors,
1459- resolveOverloads,
1460- false ,
1461- getAllSymbols
1462- )
1555+ let declaredItems = getDeclaredItemsNotInRangeOpWithAllSymbols ()
14631556
14641557 match results with
14651558 | NameResResult.Members ( items, denv, m) ->
@@ -1484,20 +1577,7 @@ type internal TypeCheckInfo
14841577 | _ -> declaredItems
14851578
14861579 | Some ( CompletionContext.AttributeApplication) ->
1487- GetDeclaredItems(
1488- parseResultsOpt,
1489- lineStr,
1490- origLongIdentOpt,
1491- colAtEndOfNamesAndResidue,
1492- residueOpt,
1493- lastDotPos,
1494- line,
1495- loc,
1496- filterCtors,
1497- resolveOverloads,
1498- false ,
1499- getAllSymbols
1500- )
1580+ getDeclaredItemsNotInRangeOpWithAllSymbols ()
15011581 |> Option.map ( fun ( items , denv , m ) ->
15021582 items
15031583 |> List.filter ( fun cItem ->
@@ -1509,20 +1589,7 @@ type internal TypeCheckInfo
15091589 m)
15101590
15111591 | Some ( CompletionContext.OpenDeclaration isOpenType) ->
1512- GetDeclaredItems(
1513- parseResultsOpt,
1514- lineStr,
1515- origLongIdentOpt,
1516- colAtEndOfNamesAndResidue,
1517- residueOpt,
1518- lastDotPos,
1519- line,
1520- loc,
1521- filterCtors,
1522- resolveOverloads,
1523- false ,
1524- getAllSymbols
1525- )
1592+ getDeclaredItemsNotInRangeOpWithAllSymbols ()
15261593 |> Option.map ( fun ( items , denv , m ) ->
15271594 items
15281595 |> List.filter ( fun x ->
@@ -1541,108 +1608,28 @@ type internal TypeCheckInfo
15411608 | Some CompletionContext.TypeAbbreviationOrSingleCaseUnion
15421609 // Completion at 'Field1: ...'
15431610 | Some ( CompletionContext.RecordField ( RecordContext.Declaration false )) ->
1544- GetDeclaredItems(
1545- parseResultsOpt,
1546- lineStr,
1547- origLongIdentOpt,
1548- colAtEndOfNamesAndResidue,
1549- residueOpt,
1550- lastDotPos,
1551- line,
1552- loc,
1553- filterCtors,
1554- resolveOverloads,
1555- false ,
1556- getAllSymbols
1557- )
1558- |> Option.map ( fun ( items , denv , m ) ->
1559- items
1560- |> List.filter ( fun cItem ->
1561- match cItem.Item with
1562- | Item.ModuleOrNamespaces _
1563- | Item.Types _
1564- | Item.TypeVar _
1565- | Item.UnqualifiedType _
1566- | Item.ExnCase _ -> true
1567- | _ -> false ),
1568- denv,
1569- m)
1570-
1571- | Some ( CompletionContext.Pattern ( PatternContext.UnionCaseFieldIdentifier ( referencedFields, caseIdRange))) ->
1572- GetUnionCaseFields caseIdRange referencedFields
1573- |> Option.map ( fun completions ->
1574- let ( nenv , _ad ), m = GetBestEnvForPos pos
1575- completions, nenv.DisplayEnv, m)
1611+ getDeclaredItemsNotInRangeOpWithAllSymbols ()
1612+ |> Option.bind ( FilterRelevantItemsBy getItem2 None IsTypeCandidate)
15761613
15771614 | Some ( CompletionContext.Pattern patternContext) ->
1578- let declaredItems =
1579- GetDeclaredItems(
1580- parseResultsOpt,
1581- lineStr,
1582- origLongIdentOpt,
1583- colAtEndOfNamesAndResidue,
1584- residueOpt,
1585- lastDotPos,
1586- line,
1587- loc,
1588- filterCtors,
1589- resolveOverloads,
1590- false ,
1591- getAllSymbols
1592- )
1593- |> Option.map ( fun ( items , denv , range ) ->
1594- let filtered =
1595- items
1596- |> List.filter ( fun item ->
1597- match item.Item with
1598- | Item.Value v -> v.LiteralValue.IsSome
1599- | Item.ILField field -> field.LiteralValue.IsSome
1600- | Item.ActivePatternCase _
1601- | Item.ExnCase _
1602- | Item.ModuleOrNamespaces _
1603- | Item.NewDef _
1604- | Item.Types _
1605- | Item.UnionCase _ -> true
1606- | _ -> false )
1607-
1608- filtered, denv, range)
1609-
1610- let indexOrName , caseIdRange =
1611- match patternContext with
1612- | PatternContext.PositionalUnionCaseField ( index, _, m) -> Choice1Of2 index, m
1613- | PatternContext.NamedUnionCaseField ( name, m) -> Choice2Of2 name, m
1614- | PatternContext.UnionCaseFieldIdentifier _
1615- | PatternContext.Other -> Choice1Of2 None, range0
1616-
1617- // No special handling other than filtering out items that may not appear in a pattern
1618- if equals caseIdRange range0 then
1619- declaredItems
1620- else
1621- // When the user types `fun (Case (x| )) ->`, we do not yet know whether the intention is to use positional or named arguments,
1622- // so let's show options for both.
1623- let fields patternContext ( uci : UnionCaseInfo ) =
1624- match patternContext with
1625- | PatternContext.PositionalUnionCaseField ( Some 0 , true , _) ->
1626- uci.UnionCase.RecdFields
1627- |> List.mapi ( fun index _ ->
1628- Item.UnionCaseField( uci, index)
1629- |> ItemWithNoInst
1630- |> CompletionItem ValueNone ValueNone)
1631- | _ -> []
1632-
1633- sResolutions.CapturedNameResolutions
1634- |> ResizeArray.tryPick ( fun r ->
1635- match r.Item with
1636- | Item.UnionCase ( uci, _) when equals r.Range caseIdRange ->
1637- let list =
1638- declaredItems
1639- |> Option.map p13
1640- |> Option.defaultValue []
1641- |> List.append ( fields patternContext uci)
1642-
1643- Some( SuggestNameForUnionCaseFieldPattern g caseIdRange.End pos uci indexOrName list, r.DisplayEnv, r.Range)
1644- | _ -> None)
1645- |> Option.orElse declaredItems
1615+ match patternContext with
1616+ | PatternContext.UnionCaseFieldIdentifier ( referencedFields, caseIdRange) ->
1617+ GetUnionCaseFields caseIdRange referencedFields
1618+ |> Option.map ( fun completions ->
1619+ let ( nenv , _ad ), m = GetBestEnvForPos pos
1620+ completions, nenv.DisplayEnv, m)
1621+ | PatternContext.PositionalUnionCaseField ( fieldIndex, isTheOnlyField, caseIdRange) ->
1622+ getDeclaredItemsNotInRangeOpWithAllSymbols ()
1623+ |> GetCompletionsForUnionCaseField pos ( Choice1Of2 fieldIndex) caseIdRange isTheOnlyField
1624+ | PatternContext.NamedUnionCaseField ( fieldName, caseIdRange) ->
1625+ getDeclaredItemsNotInRangeOpWithAllSymbols ()
1626+ |> GetCompletionsForUnionCaseField pos ( Choice2Of2 fieldName) caseIdRange false
1627+ | PatternContext.RecordFieldIdentifier referencedFields ->
1628+ getDeclaredItemsNotInRangeOpWithAllSymbols ()
1629+ |> GetCompletionsForRecordField pos referencedFields
1630+ | PatternContext.Other ->
1631+ getDeclaredItemsNotInRangeOpWithAllSymbols ()
1632+ |> Option.bind ( FilterRelevantItemsBy getItem2 None IsPatternCandidate)
16461633
16471634 | Some ( CompletionContext.MethodOverride enclosingTypeNameRange) -> GetOverridableMethods pos enclosingTypeNameRange
16481635
0 commit comments