@@ -800,6 +800,28 @@ type internal TypeCheckInfo
800
800
| Item.Types (_, ty :: _) when isInterfaceTy g ty -> true
801
801
| _ -> false
802
802
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
+
803
825
/// Return only items with the specified name, modulo "Attribute" for type completions
804
826
let FilterDeclItemsByResidue ( getItem : 'a -> Item ) residue ( items : 'a list ) =
805
827
let attributedResidue = residue + " Attribute"
@@ -939,6 +961,10 @@ type internal TypeCheckInfo
939
961
Unresolved = None
940
962
}
941
963
964
+ let getItem ( x : ItemWithInst ) = x.Item
965
+
966
+ let getItem2 ( x : CompletionItem ) = x.Item
967
+
942
968
/// Checks whether the suggested name is unused.
943
969
/// In the future we could use an increasing numeric suffix for conflict resolution
944
970
let CreateCompletionItemForSuggestedPatternName ( pos : pos ) name =
@@ -1044,7 +1070,7 @@ type internal TypeCheckInfo
1044
1070
|> List.map ( fun ( name , overloads ) ->
1045
1071
Item.MethodGroup( name, overloads, None)
1046
1072
|> ItemWithNoInst
1047
- |> CompletionItem ValueNone ValueNone )
1073
+ |> DefaultCompletionItem )
1048
1074
1049
1075
Some( overridableMethods, nenv.DisplayEnv, m)
1050
1076
| _ -> None)
@@ -1063,12 +1089,77 @@ type internal TypeCheckInfo
1063
1089
else
1064
1090
Item.UnionCaseField( uci, index)
1065
1091
|> ItemWithNoInst
1066
- |> CompletionItem ValueNone ValueNone
1092
+ |> DefaultCompletionItem
1067
1093
|> Some)
1068
1094
|> Some
1069
1095
| _ -> None)
1070
1096
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)
1072
1163
1073
1164
let GetDeclaredItems
1074
1165
(
@@ -1316,6 +1407,22 @@ type internal TypeCheckInfo
1316
1407
| atStart when atStart = 0 -> 0
1317
1408
| otherwise -> otherwise - 1
1318
1409
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
+
1319
1426
let pos = mkPos line colAtEndOfNamesAndResidue
1320
1427
1321
1428
// Look for a "special" completion context
@@ -1445,21 +1552,7 @@ type internal TypeCheckInfo
1445
1552
| Some ( CompletionContext.ParameterList ( endPos, fields)) ->
1446
1553
let results = GetNamedParametersAndSettableFields endPos
1447
1554
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 ()
1463
1556
1464
1557
match results with
1465
1558
| NameResResult.Members ( items, denv, m) ->
@@ -1484,20 +1577,7 @@ type internal TypeCheckInfo
1484
1577
| _ -> declaredItems
1485
1578
1486
1579
| 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 ()
1501
1581
|> Option.map ( fun ( items , denv , m ) ->
1502
1582
items
1503
1583
|> List.filter ( fun cItem ->
@@ -1509,20 +1589,7 @@ type internal TypeCheckInfo
1509
1589
m)
1510
1590
1511
1591
| 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 ()
1526
1593
|> Option.map ( fun ( items , denv , m ) ->
1527
1594
items
1528
1595
|> List.filter ( fun x ->
@@ -1541,108 +1608,28 @@ type internal TypeCheckInfo
1541
1608
| Some CompletionContext.TypeAbbreviationOrSingleCaseUnion
1542
1609
// Completion at 'Field1: ...'
1543
1610
| 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)
1576
1613
1577
1614
| 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)
1646
1633
1647
1634
| Some ( CompletionContext.MethodOverride enclosingTypeNameRange) -> GetOverridableMethods pos enclosingTypeNameRange
1648
1635
0 commit comments