@@ -1274,6 +1274,9 @@ CalleeCandidateInfo::evaluateCloseness(DeclContext *dc, Type candArgListType,
1274
1274
void missingArgument (unsigned paramIdx) override {
1275
1275
result = CC_ArgumentCountMismatch;
1276
1276
}
1277
+ void missingLabel (unsigned paramIdx) override {
1278
+ result = CC_ArgumentLabelMismatch;
1279
+ }
1277
1280
void outOfOrderArgument (unsigned argIdx, unsigned prevArgIdx) override {
1278
1281
result = CC_ArgumentLabelMismatch;
1279
1282
}
@@ -4671,152 +4674,159 @@ static bool diagnoseSingleCandidateFailures(CalleeCandidateInfo &CCI,
4671
4674
CCI.closeness != CC_ArgumentCountMismatch)
4672
4675
return false ;
4673
4676
4674
- SmallVector<Identifier, 4 > correctNames;
4675
- unsigned OOOArgIdx = ~0U , OOOPrevArgIdx = ~0U ;
4676
- unsigned extraArgIdx = ~0U , missingParamIdx = ~0U ;
4677
-
4678
4677
// If we have a single candidate that failed to match the argument list,
4679
4678
// attempt to use matchCallArguments to diagnose the problem.
4680
- struct OurListener : public MatchCallArgumentListener {
4681
- SmallVectorImpl<Identifier> &correctNames;
4682
- unsigned &OOOArgIdx, &OOOPrevArgIdx;
4683
- unsigned &extraArgIdx, &missingParamIdx;
4679
+ class ArgumentDiagnostic : public MatchCallArgumentListener {
4680
+ TypeChecker &TC;
4681
+ Expr *ArgExpr;
4682
+ llvm::SmallVectorImpl<CallArgParam> &Parameters;
4683
+ llvm::SmallVectorImpl<CallArgParam> &Arguments;
4684
+
4685
+ CalleeCandidateInfo CandidateInfo;
4686
+
4687
+ // Indicates if problem has been found and diagnostic was emitted.
4688
+ bool Diagnosed = false ;
4689
+ // Indicates if functions we are trying to call is a subscript.
4690
+ bool IsSubscript;
4691
+
4692
+ // Stores parameter bindings determined by call to matchCallArguments.
4693
+ SmallVector<ParamBinding, 4 > Bindings;
4684
4694
4685
4695
public:
4686
- OurListener (SmallVectorImpl<Identifier> &correctNames,
4687
- unsigned &OOOArgIdx, unsigned &OOOPrevArgIdx,
4688
- unsigned &extraArgIdx, unsigned &missingParamIdx)
4689
- : correctNames(correctNames),
4690
- OOOArgIdx (OOOArgIdx), OOOPrevArgIdx(OOOPrevArgIdx),
4691
- extraArgIdx(extraArgIdx), missingParamIdx(missingParamIdx) {}
4692
- void extraArgument (unsigned argIdx) override {
4693
- extraArgIdx = argIdx;
4694
- }
4695
- void missingArgument (unsigned paramIdx) override {
4696
- missingParamIdx = paramIdx;
4696
+ ArgumentDiagnostic (Expr *argExpr,
4697
+ llvm::SmallVectorImpl<CallArgParam> ¶ms,
4698
+ llvm::SmallVectorImpl<CallArgParam> &args,
4699
+ CalleeCandidateInfo &CCI, bool isSubscript)
4700
+ : TC(CCI.CS->TC), ArgExpr(argExpr), Parameters(params), Arguments(args),
4701
+ CandidateInfo (CCI), IsSubscript(isSubscript) {}
4702
+
4703
+ void extraArgument (unsigned extraArgIdx) override {
4704
+ auto name = Arguments[extraArgIdx].Label ;
4705
+ Expr *arg = ArgExpr;
4706
+
4707
+ auto tuple = dyn_cast<TupleExpr>(ArgExpr);
4708
+ if (tuple)
4709
+ arg = tuple->getElement (extraArgIdx);
4710
+
4711
+ auto loc = arg->getLoc ();
4712
+ if (tuple && extraArgIdx == tuple->getNumElements () - 1 &&
4713
+ tuple->hasTrailingClosure ())
4714
+ TC.diagnose (loc, diag::extra_trailing_closure_in_call)
4715
+ .highlight (arg->getSourceRange ());
4716
+ else if (Parameters.empty ())
4717
+ TC.diagnose (loc, diag::extra_argument_to_nullary_call)
4718
+ .highlight (ArgExpr->getSourceRange ());
4719
+ else if (name.empty ())
4720
+ TC.diagnose (loc, diag::extra_argument_positional)
4721
+ .highlight (arg->getSourceRange ());
4722
+ else
4723
+ TC.diagnose (loc, diag::extra_argument_named, name)
4724
+ .highlight (arg->getSourceRange ());
4725
+
4726
+ Diagnosed = true ;
4697
4727
}
4698
- void outOfOrderArgument (unsigned argIdx, unsigned prevArgIdx) override {
4699
- OOOArgIdx = argIdx;
4700
- OOOPrevArgIdx = prevArgIdx;
4728
+
4729
+ void missingArgument (unsigned missingParamIdx) override {
4730
+ Identifier name = Parameters[missingParamIdx].Label ;
4731
+ auto loc = ArgExpr->getStartLoc ();
4732
+ if (name.empty ())
4733
+ TC.diagnose (loc, diag::missing_argument_positional,
4734
+ missingParamIdx + 1 );
4735
+ else
4736
+ TC.diagnose (loc, diag::missing_argument_named, name);
4737
+
4738
+ auto candidate = CandidateInfo[0 ];
4739
+ if (candidate.getDecl ())
4740
+ TC.diagnose (candidate.getDecl (), diag::decl_declared_here,
4741
+ candidate.getDecl ()->getFullName ());
4742
+
4743
+ Diagnosed = true ;
4701
4744
}
4702
- bool relabelArguments (ArrayRef<Identifier> newNames) override {
4703
- correctNames.append (newNames.begin (), newNames.end ());
4704
- return true ;
4745
+
4746
+ void missingLabel (unsigned paramIdx) override {
4747
+ auto tuple = cast<TupleExpr>(ArgExpr);
4748
+ TC.diagnose (tuple->getElement (paramIdx)->getStartLoc (),
4749
+ diag::missing_argument_labels, false ,
4750
+ Parameters[paramIdx].Label .str (), IsSubscript);
4751
+
4752
+ Diagnosed = true ;
4705
4753
}
4706
- } listener(correctNames, OOOArgIdx, OOOPrevArgIdx,
4707
- extraArgIdx, missingParamIdx);
4708
4754
4709
- // Use matchCallArguments to determine how close the argument list is (in
4710
- // shape) to the specified candidates parameters. This ignores the
4711
- // concrete types of the arguments, looking only at the argument labels.
4712
- SmallVector<ParamBinding, 4 > paramBindings;
4713
- if (!matchCallArguments(args, params, CCI.hasTrailingClosure,
4714
- /* allowFixes:*/ true , listener, paramBindings))
4715
- return false ;
4755
+ void outOfOrderArgument (unsigned argIdx, unsigned prevArgIdx) override {
4756
+ auto tuple = cast<TupleExpr>(ArgExpr);
4757
+ Identifier first = tuple->getElementName (argIdx);
4758
+ Identifier second = tuple->getElementName (prevArgIdx);
4759
+
4760
+ // Build a mapping from arguments to parameters.
4761
+ SmallVector<unsigned , 4 > argBindings (tuple->getNumElements ());
4762
+ for (unsigned paramIdx = 0 ; paramIdx != Bindings.size (); ++paramIdx) {
4763
+ for (auto argIdx : Bindings[paramIdx])
4764
+ argBindings[argIdx] = paramIdx;
4765
+ }
4716
4766
4767
+ auto argRange = [&](unsigned argIdx, Identifier label) -> SourceRange {
4768
+ auto range = tuple->getElement (argIdx)->getSourceRange ();
4769
+ if (!label.empty ())
4770
+ range.Start = tuple->getElementNameLoc (argIdx);
4717
4771
4718
- // If we are missing a parameter, diagnose that.
4719
- if (missingParamIdx != ~0U ) {
4720
- Identifier name = params[missingParamIdx].Label ;
4721
- auto loc = argExpr->getStartLoc ();
4722
- if (name.empty ())
4723
- TC.diagnose (loc, diag::missing_argument_positional,
4724
- missingParamIdx+1 );
4725
- else
4726
- TC.diagnose (loc, diag::missing_argument_named, name);
4727
-
4728
- if (candidate.getDecl ())
4729
- TC.diagnose (candidate.getDecl (), diag::decl_declared_here,
4730
- candidate.getDecl ()->getFullName ());
4731
- return true ;
4732
- }
4772
+ unsigned paramIdx = argBindings[argIdx];
4773
+ if (Bindings[paramIdx].size () > 1 )
4774
+ range.End = tuple->getElement (Bindings[paramIdx].back ())->getEndLoc ();
4733
4775
4734
- if (extraArgIdx != ~0U ) {
4735
- auto name = args[extraArgIdx].Label ;
4736
- Expr *arg = argExpr;
4737
- auto tuple = dyn_cast<TupleExpr>(argExpr);
4738
- if (tuple)
4739
- arg = tuple->getElement (extraArgIdx);
4740
- auto loc = arg->getLoc ();
4741
- if (tuple && extraArgIdx == tuple->getNumElements ()-1 &&
4742
- tuple->hasTrailingClosure ())
4743
- TC.diagnose (loc, diag::extra_trailing_closure_in_call)
4744
- .highlight (arg->getSourceRange ());
4745
- else if (params.empty ())
4746
- TC.diagnose (loc, diag::extra_argument_to_nullary_call)
4747
- .highlight (argExpr->getSourceRange ());
4748
- else if (name.empty ())
4749
- TC.diagnose (loc, diag::extra_argument_positional)
4750
- .highlight (arg->getSourceRange ());
4751
- else
4752
- TC.diagnose (loc, diag::extra_argument_named, name)
4753
- .highlight (arg->getSourceRange ());
4754
- return true ;
4755
- }
4776
+ return range;
4777
+ };
4756
4778
4757
- // If this is an argument label mismatch, then diagnose that error now.
4758
- if (!correctNames.empty() &&
4759
- diagnoseArgumentLabelError (TC, argExpr, correctNames,
4760
- isa<SubscriptExpr>(fnExpr)))
4761
- return true ;
4779
+ auto firstRange = argRange (argIdx, first);
4780
+ auto secondRange = argRange (prevArgIdx, second);
4781
+
4782
+ SourceLoc diagLoc = firstRange.Start ;
4783
+
4784
+ if (first.empty () && second.empty ()) {
4785
+ TC.diagnose (diagLoc, diag::argument_out_of_order_unnamed_unnamed,
4786
+ argIdx + 1 , prevArgIdx + 1 )
4787
+ .fixItExchange (firstRange, secondRange);
4788
+ } else if (first.empty () && !second.empty ()) {
4789
+ TC.diagnose (diagLoc, diag::argument_out_of_order_unnamed_named,
4790
+ argIdx + 1 , second)
4791
+ .fixItExchange (firstRange, secondRange);
4792
+ } else if (!first.empty () && second.empty ()) {
4793
+ TC.diagnose (diagLoc, diag::argument_out_of_order_named_unnamed, first,
4794
+ prevArgIdx + 1 )
4795
+ .fixItExchange (firstRange, secondRange);
4796
+ } else {
4797
+ TC.diagnose (diagLoc, diag::argument_out_of_order_named_named, first,
4798
+ second)
4799
+ .fixItExchange (firstRange, secondRange);
4800
+ }
4762
4801
4763
- // If we have an out-of-order argument, diagnose it as such.
4764
- if (OOOArgIdx != ~0U && isa<TupleExpr>(argExpr)) {
4765
- auto tuple = cast<TupleExpr>(argExpr);
4766
- Identifier first = tuple->getElementName (OOOArgIdx);
4767
- Identifier second = tuple->getElementName (OOOPrevArgIdx);
4768
-
4769
- // Build a mapping from arguments to parameters.
4770
- SmallVector<unsigned , 4 > argBindings (tuple->getNumElements ());
4771
- for (unsigned paramIdx = 0 ; paramIdx != paramBindings.size (); ++paramIdx) {
4772
- for (auto argIdx : paramBindings[paramIdx])
4773
- argBindings[argIdx] = paramIdx;
4774
- }
4775
-
4776
- auto firstRange = tuple->getElement (OOOArgIdx)->getSourceRange ();
4777
- if (!first.empty ()) {
4778
- firstRange.Start = tuple->getElementNameLoc (OOOArgIdx);
4779
- }
4780
- unsigned OOOParamIdx = argBindings[OOOArgIdx];
4781
- if (paramBindings[OOOParamIdx].size () > 1 ) {
4782
- firstRange.End =
4783
- tuple->getElement (paramBindings[OOOParamIdx].back ())->getEndLoc ();
4784
- }
4785
-
4786
- auto secondRange = tuple->getElement (OOOPrevArgIdx)->getSourceRange ();
4787
- if (!second.empty ()) {
4788
- secondRange.Start = tuple->getElementNameLoc (OOOPrevArgIdx);
4789
- }
4790
- unsigned OOOPrevParamIdx = argBindings[OOOPrevArgIdx];
4791
- if (paramBindings[OOOPrevParamIdx].size () > 1 ) {
4792
- secondRange.End =
4793
- tuple->getElement (paramBindings[OOOPrevParamIdx].back ())->getEndLoc ();
4794
- }
4795
-
4796
- SourceLoc diagLoc = firstRange.Start ;
4797
-
4798
- if (first.empty () && second.empty ()) {
4799
- TC.diagnose (diagLoc, diag::argument_out_of_order_unnamed_unnamed,
4800
- OOOArgIdx + 1 , OOOPrevArgIdx + 1 )
4801
- .fixItExchange (firstRange, secondRange);
4802
- } else if (first.empty () && !second.empty ()) {
4803
- TC.diagnose (diagLoc, diag::argument_out_of_order_unnamed_named,
4804
- OOOArgIdx + 1 , second)
4805
- .fixItExchange (firstRange, secondRange);
4806
- } else if (!first.empty () && second.empty ()) {
4807
- TC.diagnose (diagLoc, diag::argument_out_of_order_named_unnamed,
4808
- first, OOOPrevArgIdx + 1 )
4809
- .fixItExchange (firstRange, secondRange);
4810
- } else {
4811
- TC.diagnose (diagLoc, diag::argument_out_of_order_named_named,
4812
- first, second)
4813
- .fixItExchange (firstRange, secondRange);
4802
+ Diagnosed = true ;
4814
4803
}
4815
4804
4816
- return true ;
4817
- }
4805
+ bool relabelArguments (ArrayRef<Identifier> newNames) override {
4806
+ assert (!newNames. empty () && " No arguments were re-labeled " );
4818
4807
4819
- return false ;
4808
+ // Let's diagnose labeling problem but only related to corrected ones.
4809
+ if (diagnoseArgumentLabelError (TC, ArgExpr, newNames, IsSubscript))
4810
+ Diagnosed = true ;
4811
+
4812
+ return true ;
4813
+ }
4814
+
4815
+ bool diagnose () {
4816
+ // Use matchCallArguments to determine how close the argument list is (in
4817
+ // shape) to the specified candidates parameters. This ignores the
4818
+ // concrete types of the arguments, looking only at the argument labels.
4819
+ matchCallArguments (Arguments, Parameters,
4820
+ CandidateInfo.hasTrailingClosure ,
4821
+ /* allowFixes:*/ true , *this , Bindings);
4822
+
4823
+ return Diagnosed;
4824
+ }
4825
+ };
4826
+
4827
+ return ArgumentDiagnostic(argExpr, params, args, CCI,
4828
+ isa<SubscriptExpr>(fnExpr))
4829
+ .diagnose();
4820
4830
}
4821
4831
4822
4832
// / If the candidate set has been narrowed down to a specific structural
0 commit comments