@@ -3108,6 +3108,51 @@ static void checkSwitch(TypeChecker &TC, const SwitchStmt *stmt) {
3108
3108
}
3109
3109
}
3110
3110
3111
+ void swift::fixItEncloseTrailingClosure (TypeChecker &TC,
3112
+ InFlightDiagnostic &diag,
3113
+ const CallExpr *call,
3114
+ Identifier closureLabel) {
3115
+ auto argsExpr = call->getArg ();
3116
+ if (auto TSE = dyn_cast<TupleShuffleExpr>(argsExpr))
3117
+ argsExpr = TSE->getSubExpr ();
3118
+
3119
+ SmallString<32 > replacement;
3120
+ SourceLoc lastLoc;
3121
+ SourceRange closureRange;
3122
+ if (auto PE = dyn_cast<ParenExpr>(argsExpr)) {
3123
+ assert (PE->hasTrailingClosure () && " must have trailing closure" );
3124
+ closureRange = PE->getSubExpr ()->getSourceRange ();
3125
+ lastLoc = PE->getLParenLoc (); // e.g funcName() { 1 }
3126
+ if (!lastLoc.isValid ()) {
3127
+ // Bare trailing closure: e.g. funcName { 1 }
3128
+ replacement = " (" ;
3129
+ lastLoc = call->getFn ()->getEndLoc ();
3130
+ }
3131
+ } else if (auto TE = dyn_cast<TupleExpr>(argsExpr)) {
3132
+ // Tuple + trailing closure: e.g. funcName(x: 1) { 1 }
3133
+ assert (TE->hasTrailingClosure () && " must have trailing closure" );
3134
+ auto numElements = TE->getNumElements ();
3135
+ assert (numElements >= 2 && " Unexpected num of elements in TupleExpr" );
3136
+ closureRange = TE->getElement (numElements - 1 )->getSourceRange ();
3137
+ lastLoc = TE->getElement (numElements - 2 )->getEndLoc ();
3138
+ replacement = " , " ;
3139
+ } else {
3140
+ // Can't be here.
3141
+ return ;
3142
+ }
3143
+
3144
+ // Add argument label of the closure.
3145
+ if (!closureLabel.empty ()) {
3146
+ replacement += closureLabel.str ();
3147
+ replacement += " : " ;
3148
+ }
3149
+
3150
+ lastLoc = Lexer::getLocForEndOfToken (TC.Context .SourceMgr , lastLoc);
3151
+ diag
3152
+ .fixItReplaceChars (lastLoc, closureRange.Start , replacement)
3153
+ .fixItInsertAfter (closureRange.End , " )" );
3154
+ }
3155
+
3111
3156
// Perform checkStmtConditionTrailingClosure for single expression.
3112
3157
static void checkStmtConditionTrailingClosure (TypeChecker &TC, const Expr *E) {
3113
3158
if (E == nullptr || isa<ErrorExpr>(E)) return ;
@@ -3117,63 +3162,31 @@ static void checkStmtConditionTrailingClosure(TypeChecker &TC, const Expr *E) {
3117
3162
TypeChecker &TC;
3118
3163
3119
3164
void diagnoseIt (const CallExpr *E) {
3165
+ if (!E->hasTrailingClosure ()) return ;
3166
+
3120
3167
auto argsExpr = E->getArg ();
3121
3168
auto argsTy = argsExpr->getType ();
3122
-
3123
3169
// Ignore invalid argument type. Some diagnostics are already emitted.
3124
3170
if (!argsTy || argsTy->is <ErrorType>()) return ;
3125
3171
3126
3172
if (auto TSE = dyn_cast<TupleShuffleExpr>(argsExpr))
3127
3173
argsExpr = TSE->getSubExpr ();
3128
3174
3129
- SmallString<16 > replacement;
3130
- SourceLoc lastLoc;
3131
- SourceRange closureRange;
3132
- if (auto PE = dyn_cast<ParenExpr>(argsExpr)) {
3133
- // Ignore non-trailing-closure.
3134
- if (!PE->hasTrailingClosure ()) return ;
3135
-
3136
- closureRange = PE->getSubExpr ()->getSourceRange ();
3137
- lastLoc = PE->getLParenLoc ();
3138
- if (lastLoc.isValid ()) {
3139
- // Empty paren: e.g. if funcName() { 1 } { ... }
3140
- replacement = " " ;
3141
- } else {
3142
- // Bare trailing closure: e.g. if funcName { 1 } { ... }
3143
- replacement = " (" ;
3144
- lastLoc = E->getFn ()->getEndLoc ();
3145
- }
3146
- } else if (auto TE = dyn_cast<TupleExpr>(argsExpr)) {
3147
- // Ignore non-trailing-closure.
3148
- if (!TE->hasTrailingClosure ()) return ;
3149
-
3150
- // Tuple + trailing closure: e.g. if funcName(x: 1) { 1 } { ... }
3151
- auto numElements = TE->getNumElements ();
3152
- assert (numElements >= 2 && " Unexpected num of elements in TupleExpr" );
3153
- closureRange = TE->getElement (numElements - 1 )->getSourceRange ();
3154
- lastLoc = TE->getElement (numElements - 2 )->getEndLoc ();
3155
- replacement = " , " ;
3156
- } else {
3157
- // Can't be here.
3158
- return ;
3159
- }
3175
+ SourceLoc closureLoc;
3176
+ if (auto PE = dyn_cast<ParenExpr>(argsExpr))
3177
+ closureLoc = PE->getSubExpr ()->getStartLoc ();
3178
+ else if (auto TE = dyn_cast<TupleExpr>(argsExpr))
3179
+ closureLoc = TE->getElements ().back ()->getStartLoc ();
3160
3180
3161
- // Add argument label of the closure that is going to be enclosed in
3162
- // parens.
3181
+ Identifier closureLabel;
3163
3182
if (auto TT = argsTy->getAs <TupleType>()) {
3164
3183
assert (TT->getNumElements () != 0 && " Unexpected empty TupleType" );
3165
- auto closureLabel = TT->getElement (TT->getNumElements () - 1 ).getName ();
3166
- if (!closureLabel.empty ()) {
3167
- replacement += closureLabel.str ();
3168
- replacement += " : " ;
3169
- }
3184
+ closureLabel = TT->getElement (TT->getNumElements () - 1 ).getName ();
3170
3185
}
3171
3186
3172
- // Emit diagnostics.
3173
- lastLoc = Lexer::getLocForEndOfToken (TC.Context .SourceMgr , lastLoc);
3174
- TC.diagnose (closureRange.Start , diag::trailing_closure_requires_parens)
3175
- .fixItReplaceChars (lastLoc, closureRange.Start , replacement)
3176
- .fixItInsertAfter (closureRange.End , " )" );
3187
+ auto diag = TC.diagnose (closureLoc,
3188
+ diag::trailing_closure_requires_parens);
3189
+ fixItEncloseTrailingClosure (TC, diag, E, closureLabel);
3177
3190
}
3178
3191
3179
3192
public:
0 commit comments