@@ -986,8 +986,35 @@ constraints::matchCallArguments(
986
986
};
987
987
}
988
988
989
- static Optional<unsigned >
990
- getCompletionArgIndex (ASTNode anchor, ConstraintSystem &CS) {
989
+ struct CompletionArgInfo {
990
+ unsigned completionIdx;
991
+ Optional<unsigned > firstTrailingIdx;
992
+
993
+ bool isAllowableMissingArg (unsigned argInsertIdx,
994
+ AnyFunctionType::Param param) {
995
+ // If the argument is before or at the index of the argument containing the
996
+ // completion, the user would likely have already written it if they
997
+ // intended this overload.
998
+ if (completionIdx >= argInsertIdx)
999
+ return false ;
1000
+
1001
+ // If the argument is after the first trailing closure, the user can only
1002
+ // continue on to write more trailing arguments, so only allow this overload
1003
+ // if the missing argument is of function type.
1004
+ if (firstTrailingIdx && argInsertIdx > *firstTrailingIdx) {
1005
+ if (param.isInOut ())
1006
+ return false ;
1007
+
1008
+ Type expectedTy = param.getPlainType ()->lookThroughAllOptionalTypes ();
1009
+ return expectedTy->is <FunctionType>() || expectedTy->isAny () ||
1010
+ expectedTy->isTypeVariableOrMember ();
1011
+ }
1012
+ return true ;
1013
+ }
1014
+ };
1015
+
1016
+ static Optional<CompletionArgInfo>
1017
+ getCompletionArgInfo (ASTNode anchor, ConstraintSystem &CS) {
991
1018
Expr *arg = nullptr ;
992
1019
if (auto *CE = getAsExpr<CallExpr>(anchor))
993
1020
arg = CE->getArg ();
@@ -999,16 +1026,15 @@ getCompletionArgIndex(ASTNode anchor, ConstraintSystem &CS) {
999
1026
if (!arg)
1000
1027
return None;
1001
1028
1002
- if (auto *TE = dyn_cast<TupleExpr>(arg)) {
1003
- auto elems = TE->getElements ();
1004
- auto idx = llvm::find_if (elems, [&](Expr *elem) {
1005
- return CS.containsCodeCompletionLoc (elem);
1006
- });
1007
- if (idx != elems.end ())
1008
- return std::distance (elems.begin (), idx);
1009
- } else if (auto *PE = dyn_cast<ParenExpr>(arg)) {
1029
+ auto trailingIdx = arg->getUnlabeledTrailingClosureIndexOfPackedArgument ();
1030
+ if (auto *PE = dyn_cast<ParenExpr>(arg)) {
1010
1031
if (CS.containsCodeCompletionLoc (PE->getSubExpr ()))
1011
- return 0 ;
1032
+ return CompletionArgInfo{ 0 , trailingIdx };
1033
+ } else if (auto *TE = dyn_cast<TupleExpr>(arg)) {
1034
+ for (unsigned i: indices (TE->getElements ())) {
1035
+ if (CS.containsCodeCompletionLoc (TE->getElement (i)))
1036
+ return CompletionArgInfo{ i, trailingIdx };
1037
+ }
1012
1038
}
1013
1039
return None;
1014
1040
}
@@ -1021,7 +1047,7 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
1021
1047
1022
1048
SmallVector<SynthesizedArg, 4 > MissingArguments;
1023
1049
SmallVector<std::pair<unsigned , AnyFunctionType::Param>, 4 > ExtraArguments;
1024
- Optional<unsigned > CompletionArgIdx ;
1050
+ Optional<CompletionArgInfo> CompletionArgInfo ;
1025
1051
1026
1052
public:
1027
1053
ArgumentFailureTracker (ConstraintSystem &cs,
@@ -1048,10 +1074,19 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
1048
1074
const auto ¶m = Parameters[paramIdx];
1049
1075
1050
1076
unsigned newArgIdx = Arguments.size ();
1077
+
1078
+ bool isAfterCodeCompletionLoc = false ;
1079
+ if (CS.isForCodeCompletion ()) {
1080
+ if (!CompletionArgInfo)
1081
+ CompletionArgInfo = getCompletionArgInfo (Locator.getAnchor (), CS);
1082
+ isAfterCodeCompletionLoc = CompletionArgInfo &&
1083
+ CompletionArgInfo->isAllowableMissingArg (argInsertIdx, param);
1084
+ }
1085
+
1051
1086
auto *argLoc = CS.getConstraintLocator (
1052
1087
Locator, {LocatorPathElt::ApplyArgToParam (newArgIdx, paramIdx,
1053
1088
param.getParameterFlags ()),
1054
- LocatorPathElt::SynthesizedArgument (newArgIdx)});
1089
+ LocatorPathElt::SynthesizedArgument (newArgIdx, isAfterCodeCompletionLoc )});
1055
1090
1056
1091
auto *argType =
1057
1092
CS.createTypeVariable (argLoc, TVO_CanBindToInOut | TVO_CanBindToLValue |
@@ -1060,16 +1095,12 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
1060
1095
auto synthesizedArg = param.withType (argType);
1061
1096
Arguments.push_back (synthesizedArg);
1062
1097
1063
- if (CS.isForCodeCompletion ()) {
1064
- // When solving for code completion, if any argument contains the
1065
- // completion location, later arguments shouldn't be considered missing
1066
- // (causing the solution to have a worse score) as the user just hasn't
1067
- // written them yet. Early exit to avoid recording them in this case.
1068
- if (!CompletionArgIdx)
1069
- CompletionArgIdx = getCompletionArgIndex (Locator.getAnchor (), CS);
1070
- if (CompletionArgIdx && *CompletionArgIdx < argInsertIdx)
1071
- return newArgIdx;
1072
- }
1098
+ // When solving for code completion, if any argument contains the
1099
+ // completion location, later arguments shouldn't be considered missing
1100
+ // (causing the solution to have a worse score) as the user just hasn't
1101
+ // written them yet. Early exit to avoid recording them in this case.
1102
+ if (isAfterCodeCompletionLoc)
1103
+ return newArgIdx;
1073
1104
1074
1105
MissingArguments.push_back (SynthesizedArg{paramIdx, synthesizedArg});
1075
1106
0 commit comments