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