@@ -1006,36 +1006,48 @@ void swift::fixItAvailableAttrRename(TypeChecker &TC,
1006
1006
InFlightDiagnostic &diag,
1007
1007
SourceRange referenceRange,
1008
1008
const AvailableAttr *attr,
1009
- const CallExpr *CE ) {
1009
+ const ApplyExpr *call ) {
1010
1010
ParsedDeclName parsed = swift::parseDeclName (attr->Rename );
1011
1011
if (!parsed)
1012
1012
return ;
1013
1013
1014
+ bool originallyWasKnownOperatorExpr = false ;
1015
+ if (call) {
1016
+ originallyWasKnownOperatorExpr =
1017
+ isa<BinaryExpr>(call) ||
1018
+ isa<PrefixUnaryExpr>(call) ||
1019
+ isa<PostfixUnaryExpr>(call);
1020
+ }
1021
+ if (parsed.isOperator () != originallyWasKnownOperatorExpr)
1022
+ return ;
1023
+
1014
1024
SourceManager &sourceMgr = TC.Context .SourceMgr ;
1015
1025
1016
1026
if (parsed.isInstanceMember ()) {
1017
1027
// Replace the base of the call with the "self argument".
1018
1028
// We can only do a good job with the fix-it if we have the whole call
1019
1029
// expression.
1020
1030
// FIXME: Should we be validating the ContextName in some way?
1021
- if (!CE )
1031
+ if (!dyn_cast_or_null<CallExpr>(call) )
1022
1032
return ;
1023
1033
1024
1034
unsigned selfIndex = parsed.SelfIndex .getValue ();
1025
1035
const Expr *selfExpr = nullptr ;
1026
1036
SourceLoc removeRangeStart;
1027
1037
SourceLoc removeRangeEnd;
1028
1038
1029
- const Expr *argExpr = CE ->getArg ();
1039
+ const Expr *argExpr = call ->getArg ();
1030
1040
if (auto args = dyn_cast<TupleExpr>(argExpr)) {
1031
- if (selfIndex >= args->getNumElements ())
1041
+ size_t numElementsWithinParens = args->getNumElements ();
1042
+ numElementsWithinParens -= args->hasTrailingClosure ();
1043
+ if (selfIndex >= numElementsWithinParens)
1032
1044
return ;
1033
1045
1034
1046
if (parsed.IsGetter ) {
1035
- if (args-> getNumElements () != 1 )
1047
+ if (numElementsWithinParens != 1 )
1036
1048
return ;
1037
1049
} else if (parsed.IsSetter ) {
1038
- if (args-> getNumElements () != 2 )
1050
+ if (numElementsWithinParens != 2 )
1039
1051
return ;
1040
1052
} else {
1041
1053
if (parsed.ArgumentLabels .size () != args->getNumElements () - 1 )
@@ -1044,7 +1056,7 @@ void swift::fixItAvailableAttrRename(TypeChecker &TC,
1044
1056
1045
1057
selfExpr = args->getElement (selfIndex);
1046
1058
1047
- if (selfIndex + 1 == args-> getNumElements () ) {
1059
+ if (selfIndex + 1 == numElementsWithinParens ) {
1048
1060
if (selfIndex > 0 ) {
1049
1061
// Remove from the previous comma to the close-paren (half-open).
1050
1062
removeRangeStart = args->getElement (selfIndex-1 )->getEndLoc ();
@@ -1055,7 +1067,12 @@ void swift::fixItAvailableAttrRename(TypeChecker &TC,
1055
1067
removeRangeStart = Lexer::getLocForEndOfToken (sourceMgr,
1056
1068
argExpr->getStartLoc ());
1057
1069
}
1058
- removeRangeEnd = args->getEndLoc ();
1070
+
1071
+ // Prefer the r-paren location, so that we get the right behavior when
1072
+ // there's a trailing closure, but handle some implicit cases too.
1073
+ removeRangeEnd = args->getRParenLoc ();
1074
+ if (removeRangeEnd.isInvalid ())
1075
+ removeRangeEnd = args->getEndLoc ();
1059
1076
1060
1077
} else {
1061
1078
// Remove from the label to the start of the next argument (half-open).
@@ -1108,21 +1125,22 @@ void swift::fixItAvailableAttrRename(TypeChecker &TC,
1108
1125
selfReplace.push_back (' )' );
1109
1126
selfReplace.push_back (' .' );
1110
1127
selfReplace += parsed.BaseName ;
1111
- diag.fixItReplace (CE ->getFn ()->getSourceRange (), selfReplace);
1128
+ diag.fixItReplace (call ->getFn ()->getSourceRange (), selfReplace);
1112
1129
1113
1130
if (!parsed.isPropertyAccessor ())
1114
1131
diag.fixItRemoveChars (removeRangeStart, removeRangeEnd);
1115
1132
1116
1133
// Continue on to diagnose any argument label renames.
1117
1134
1118
- } else if (parsed.BaseName == TC.Context .Id_init .str () && CE) {
1135
+ } else if (parsed.BaseName == TC.Context .Id_init .str () &&
1136
+ dyn_cast_or_null<CallExpr>(call)) {
1119
1137
// For initializers, replace with a "call" of the context type...but only
1120
1138
// if we know we're doing a call (rather than a first-class reference).
1121
1139
if (parsed.isMember ()) {
1122
- diag.fixItReplace (CE ->getFn ()->getSourceRange (), parsed.ContextName );
1140
+ diag.fixItReplace (call ->getFn ()->getSourceRange (), parsed.ContextName );
1123
1141
1124
1142
} else {
1125
- auto *dotCall = dyn_cast<DotSyntaxCallExpr>(CE ->getFn ());
1143
+ auto *dotCall = dyn_cast<DotSyntaxCallExpr>(call ->getFn ());
1126
1144
if (!dotCall)
1127
1145
return ;
1128
1146
@@ -1144,10 +1162,10 @@ void swift::fixItAvailableAttrRename(TypeChecker &TC,
1144
1162
diag.fixItReplace (referenceRange, baseReplace);
1145
1163
}
1146
1164
1147
- if (!CE )
1165
+ if (!dyn_cast_or_null<CallExpr>(call) )
1148
1166
return ;
1149
1167
1150
- const Expr *argExpr = CE ->getArg ();
1168
+ const Expr *argExpr = call ->getArg ();
1151
1169
if (parsed.IsGetter ) {
1152
1170
diag.fixItRemove (argExpr->getSourceRange ());
1153
1171
return ;
@@ -1290,7 +1308,7 @@ void TypeChecker::diagnoseDeprecated(SourceRange ReferenceRange,
1290
1308
const DeclContext *ReferenceDC,
1291
1309
const AvailableAttr *Attr,
1292
1310
DeclName Name,
1293
- const CallExpr *CE ) {
1311
+ const ApplyExpr *Call ) {
1294
1312
// We match the behavior of clang to not report deprecation warnings
1295
1313
// inside declarations that are themselves deprecated on all deployment
1296
1314
// targets.
@@ -1347,7 +1365,7 @@ void TypeChecker::diagnoseDeprecated(SourceRange ReferenceRange,
1347
1365
auto renameDiag = diagnose (ReferenceRange.Start ,
1348
1366
diag::note_deprecated_rename,
1349
1367
newName);
1350
- fixItAvailableAttrRename (*this , renameDiag, ReferenceRange, Attr, CE );
1368
+ fixItAvailableAttrRename (*this , renameDiag, ReferenceRange, Attr, Call );
1351
1369
}
1352
1370
}
1353
1371
@@ -1400,11 +1418,11 @@ void TypeChecker::diagnoseUnavailableOverride(ValueDecl *override,
1400
1418
bool TypeChecker::diagnoseExplicitUnavailability (const ValueDecl *D,
1401
1419
SourceRange R,
1402
1420
const DeclContext *DC,
1403
- const CallExpr *CE ) {
1421
+ const ApplyExpr *call ) {
1404
1422
return diagnoseExplicitUnavailability (D, R, DC,
1405
1423
[=](InFlightDiagnostic &diag) {
1406
1424
fixItAvailableAttrRename (*this , diag, R, AvailableAttr::isUnavailable (D),
1407
- CE );
1425
+ call );
1408
1426
});
1409
1427
}
1410
1428
@@ -1539,19 +1557,19 @@ class AvailabilityWalker : public ASTWalker {
1539
1557
1540
1558
if (auto DR = dyn_cast<DeclRefExpr>(E))
1541
1559
diagAvailability (DR->getDecl (), DR->getSourceRange (),
1542
- getEnclosingCallExpr ());
1560
+ getEnclosingApplyExpr ());
1543
1561
if (auto MR = dyn_cast<MemberRefExpr>(E)) {
1544
1562
walkMemberRef (MR);
1545
1563
return skipChildren ();
1546
1564
}
1547
1565
if (auto OCDR = dyn_cast<OtherConstructorDeclRefExpr>(E))
1548
1566
diagAvailability (OCDR->getDecl (),
1549
1567
OCDR->getConstructorLoc ().getSourceRange (),
1550
- getEnclosingCallExpr ());
1568
+ getEnclosingApplyExpr ());
1551
1569
if (auto DMR = dyn_cast<DynamicMemberRefExpr>(E))
1552
1570
diagAvailability (DMR->getMember ().getDecl (),
1553
1571
DMR->getNameLoc ().getSourceRange (),
1554
- getEnclosingCallExpr ());
1572
+ getEnclosingApplyExpr ());
1555
1573
if (auto DS = dyn_cast<DynamicSubscriptExpr>(E))
1556
1574
diagAvailability (DS->getMember ().getDecl (), DS->getSourceRange ());
1557
1575
if (auto S = dyn_cast<SubscriptExpr>(E)) {
@@ -1579,12 +1597,12 @@ class AvailabilityWalker : public ASTWalker {
1579
1597
1580
1598
private:
1581
1599
bool diagAvailability (const ValueDecl *D, SourceRange R,
1582
- const CallExpr *CE = nullptr );
1600
+ const ApplyExpr *call = nullptr );
1583
1601
bool diagnoseIncDecRemoval (const ValueDecl *D, SourceRange R,
1584
1602
const AvailableAttr *Attr);
1585
1603
1586
- // / Walks up from a potential callee to the enclosing CallExpr .
1587
- const CallExpr * getEnclosingCallExpr () const {
1604
+ // / Walks up from a potential callee to the enclosing ApplyExpr .
1605
+ const ApplyExpr * getEnclosingApplyExpr () const {
1588
1606
ArrayRef<const Expr *> parents = ExprStack;
1589
1607
assert (!parents.empty () && " must be called while visiting an expression" );
1590
1608
size_t idx = parents.size () - 1 ;
@@ -1599,7 +1617,7 @@ class AvailabilityWalker : public ASTWalker {
1599
1617
isa<ForceValueExpr>(parents[idx]) || // f!(a)
1600
1618
isa<BindOptionalExpr>(parents[idx])); // f?(a)
1601
1619
1602
- auto *call = dyn_cast<CallExpr >(parents[idx]);
1620
+ auto *call = dyn_cast<ApplyExpr >(parents[idx]);
1603
1621
if (!call || call->getFn () != parents[idx+1 ])
1604
1622
return nullptr ;
1605
1623
return call;
@@ -1716,20 +1734,20 @@ class AvailabilityWalker : public ASTWalker {
1716
1734
// / Diagnose uses of unavailable declarations. Returns true if a diagnostic
1717
1735
// / was emitted.
1718
1736
bool AvailabilityWalker::diagAvailability (const ValueDecl *D, SourceRange R,
1719
- const CallExpr *CE ) {
1737
+ const ApplyExpr *call ) {
1720
1738
if (!D)
1721
1739
return false ;
1722
1740
1723
1741
if (auto *attr = AvailableAttr::isUnavailable (D))
1724
1742
if (diagnoseIncDecRemoval (D, R, attr))
1725
1743
return true ;
1726
1744
1727
- if (TC.diagnoseExplicitUnavailability (D, R, DC, CE ))
1745
+ if (TC.diagnoseExplicitUnavailability (D, R, DC, call ))
1728
1746
return true ;
1729
1747
1730
1748
// Diagnose for deprecation
1731
1749
if (const AvailableAttr *Attr = TypeChecker::getDeprecated (D)) {
1732
- TC.diagnoseDeprecated (R, DC, Attr, D->getFullName (), CE );
1750
+ TC.diagnoseDeprecated (R, DC, Attr, D->getFullName (), call );
1733
1751
}
1734
1752
1735
1753
if (TC.getLangOpts ().DisableAvailabilityChecking )
0 commit comments