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