@@ -40,7 +40,8 @@ MatchCallArgumentListener::~MatchCallArgumentListener() { }
4040bool MatchCallArgumentListener::extraArgument (unsigned argIdx) { return true ; }
4141
4242Optional<unsigned >
43- MatchCallArgumentListener::missingArgument (unsigned paramIdx) {
43+ MatchCallArgumentListener::missingArgument (unsigned paramIdx,
44+ unsigned argInsertIdx) {
4445 return None;
4546}
4647
@@ -701,11 +702,14 @@ static bool matchCallArgumentsImpl(
701702 }
702703
703704 // If we have any unfulfilled parameters, check them now.
705+ Optional<unsigned > prevArgIdx;
704706 if (haveUnfulfilledParams) {
705707 for (auto paramIdx : indices (params)) {
706708 // If we have a binding for this parameter, we're done.
707- if (!parameterBindings[paramIdx].empty ())
709+ if (!parameterBindings[paramIdx].empty ()) {
710+ prevArgIdx = parameterBindings[paramIdx].back ();
708711 continue ;
712+ }
709713
710714 const auto ¶m = params[paramIdx];
711715
@@ -717,7 +721,8 @@ static bool matchCallArgumentsImpl(
717721 if (paramInfo.hasDefaultArgument (paramIdx))
718722 continue ;
719723
720- if (auto newArgIdx = listener.missingArgument (paramIdx)) {
724+ unsigned argInsertIdx = prevArgIdx ? *prevArgIdx + 1 : 0 ;
725+ if (auto newArgIdx = listener.missingArgument (paramIdx, argInsertIdx)) {
721726 parameterBindings[paramIdx].push_back (*newArgIdx);
722727 continue ;
723728 }
@@ -980,14 +985,47 @@ constraints::matchCallArguments(
980985 };
981986}
982987
988+ static Optional<unsigned >
989+ getCompletionArgIndex (ASTNode anchor, SourceManager &SM) {
990+ Expr *arg = nullptr ;
991+ if (auto *CE = getAsExpr<CallExpr>(anchor))
992+ arg = CE->getArg ();
993+ if (auto *SE = getAsExpr<SubscriptExpr>(anchor))
994+ arg = SE->getIndex ();
995+ if (auto *OLE = getAsExpr<ObjectLiteralExpr>(anchor))
996+ arg = OLE->getArg ();
997+
998+ if (!arg)
999+ return None;
1000+
1001+ auto containsCompletion = [&](Expr *elem) {
1002+ if (!elem)
1003+ return false ;
1004+ SourceRange range = elem->getSourceRange ();
1005+ return range.isValid () && SM.rangeContainsCodeCompletionLoc (range);
1006+ };
1007+
1008+ if (auto *TE = dyn_cast<TupleExpr>(arg)) {
1009+ auto elems = TE->getElements ();
1010+ auto idx = llvm::find_if (elems, containsCompletion);
1011+ if (idx != elems.end ())
1012+ return std::distance (elems.begin (), idx);
1013+ } else if (auto *PE = dyn_cast<ParenExpr>(arg)) {
1014+ if (containsCompletion (PE->getSubExpr ()))
1015+ return 0 ;
1016+ }
1017+ return None;
1018+ }
1019+
9831020class ArgumentFailureTracker : public MatchCallArgumentListener {
9841021 ConstraintSystem &CS;
9851022 SmallVectorImpl<AnyFunctionType::Param> &Arguments;
9861023 ArrayRef<AnyFunctionType::Param> Parameters;
9871024 ConstraintLocatorBuilder Locator;
9881025
989- SmallVector<std::pair< unsigned , AnyFunctionType::Param> , 4 > MissingArguments;
1026+ SmallVector<SynthesizedArg , 4 > MissingArguments;
9901027 SmallVector<std::pair<unsigned , AnyFunctionType::Param>, 4 > ExtraArguments;
1028+ Optional<unsigned > CompletionArgIdx;
9911029
9921030public:
9931031 ArgumentFailureTracker (ConstraintSystem &cs,
@@ -1006,7 +1044,8 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
10061044 }
10071045 }
10081046
1009- Optional<unsigned > missingArgument (unsigned paramIdx) override {
1047+ Optional<unsigned > missingArgument (unsigned paramIdx,
1048+ unsigned argInsertIdx) override {
10101049 if (!CS.shouldAttemptFixes ())
10111050 return None;
10121051
@@ -1023,10 +1062,22 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
10231062 TVO_CanBindToNoEscape | TVO_CanBindToHole);
10241063
10251064 auto synthesizedArg = param.withType (argType);
1026-
1027- MissingArguments.push_back (std::make_pair (paramIdx, synthesizedArg));
10281065 Arguments.push_back (synthesizedArg);
10291066
1067+ if (CS.isForCodeCompletion ()) {
1068+ // When solving for code completion, if any argument contains the
1069+ // completion location, later arguments shouldn't be considered missing
1070+ // (causing the solution to have a worse score) as the user just hasn't
1071+ // written them yet. Early exit to avoid recording them in this case.
1072+ SourceManager &SM = CS.getASTContext ().SourceMgr ;
1073+ if (!CompletionArgIdx)
1074+ CompletionArgIdx = getCompletionArgIndex (Locator.getAnchor (), SM);
1075+ if (CompletionArgIdx && *CompletionArgIdx < argInsertIdx)
1076+ return newArgIdx;
1077+ }
1078+
1079+ MissingArguments.push_back (SynthesizedArg{paramIdx, synthesizedArg});
1080+
10301081 return newArgIdx;
10311082 }
10321083
@@ -1190,12 +1241,11 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
11901241 argsWithLabels.pop_back ();
11911242 // Let's make sure that labels associated with tuple elements
11921243 // line up with what is expected by argument list.
1193- SmallVector<std::pair<unsigned , AnyFunctionType::Param>, 4 >
1194- synthesizedArgs;
1244+ SmallVector<SynthesizedArg, 4 > synthesizedArgs;
11951245 for (unsigned i = 0 , n = argTuple->getNumElements (); i != n; ++i) {
11961246 const auto &elt = argTuple->getElement (i);
11971247 AnyFunctionType::Param argument (elt.getType (), elt.getName ());
1198- synthesizedArgs.push_back (std::make_pair ( i, argument) );
1248+ synthesizedArgs.push_back (SynthesizedArg{ i, argument} );
11991249 argsWithLabels.push_back (argument);
12001250 }
12011251
@@ -1771,15 +1821,27 @@ static bool fixMissingArguments(ConstraintSystem &cs, ASTNode anchor,
17711821 cs.createTypeVariable (argLoc, TVO_CanBindToNoEscape)));
17721822 }
17731823
1774- SmallVector<std::pair< unsigned , AnyFunctionType::Param> , 4 > synthesizedArgs;
1824+ SmallVector<SynthesizedArg , 4 > synthesizedArgs;
17751825 synthesizedArgs.reserve (numMissing);
17761826 for (unsigned i = args.size () - numMissing, n = args.size (); i != n; ++i) {
1777- synthesizedArgs.push_back (std::make_pair (i, args[i]));
1827+ synthesizedArgs.push_back (SynthesizedArg{i, args[i]});
1828+ }
1829+
1830+ // Treat missing anonymous arguments as valid in closures containing the
1831+ // code completion location, since they may have just not been written yet.
1832+ if (cs.isForCodeCompletion ()) {
1833+ if (auto *closure = getAsExpr<ClosureExpr>(anchor)) {
1834+ SourceManager &SM = closure->getASTContext ().SourceMgr ;
1835+ SourceRange range = closure->getSourceRange ();
1836+ if (range.isValid () && SM.rangeContainsCodeCompletionLoc (range) &&
1837+ (closure->hasAnonymousClosureVars () ||
1838+ (args.empty () && closure->getInLoc ().isInvalid ())))
1839+ return false ;
1840+ }
17781841 }
17791842
17801843 auto *fix = AddMissingArguments::create (cs, synthesizedArgs,
17811844 cs.getConstraintLocator (locator));
1782-
17831845 if (cs.recordFix (fix))
17841846 return true ;
17851847
@@ -3966,7 +4028,7 @@ bool ConstraintSystem::repairFailures(
39664028 // to diagnose this as a missing argument which can't be ignored.
39674029 if (arg != getTypeVariables ().end ()) {
39684030 conversionsOrFixes.push_back (AddMissingArguments::create (
3969- *this , {std::make_pair ( 0 , AnyFunctionType::Param (*arg)) },
4031+ *this , {SynthesizedArg{ 0 , AnyFunctionType::Param (*arg)} },
39704032 getConstraintLocator (anchor, path)));
39714033 break ;
39724034 }
0 commit comments