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