@@ -3291,35 +3291,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3291
3291
}
3292
3292
3293
3293
void tryPostfixOperator (Expr *expr, PostfixOperatorDecl *op) {
3294
- auto Ty = expr->getType ();
3295
- if (!Ty)
3294
+ ConcreteDeclRef referencedDecl;
3295
+ FunctionType *funcTy = getTypeOfCompletionOperator (
3296
+ const_cast <DeclContext *>(CurrDeclContext), expr, op->getName (),
3297
+ DeclRefKind::PostfixOperator, referencedDecl);
3298
+ if (!funcTy)
3296
3299
return ;
3297
3300
3298
- SWIFT_DEFER {
3299
- // Restore type.
3300
- // FIXME: This is workaround for getTypeOfExpressionWithoutApplying()
3301
- // modifies type of 'expr'.
3302
- expr->setType (Ty);
3303
- prepareForRetypechecking (expr);
3304
- };
3305
-
3306
- // We allocate these expressions on the stack because we know they can't
3307
- // escape and there isn't a better way to allocate scratch Expr nodes.
3308
- UnresolvedDeclRefExpr UDRE (op->getName (), DeclRefKind::PostfixOperator,
3309
- DeclNameLoc (expr->getSourceRange ().End ));
3310
- ParenExpr parenExpr (expr->getSourceRange ().Start , expr,
3311
- expr->getSourceRange ().End ,
3312
- /* hasTrailingClosure=*/ false );
3313
- PostfixUnaryExpr opExpr (&UDRE, &parenExpr);
3314
- Expr *tempExpr = &opExpr;
3315
- ConcreteDeclRef referencedDecl;
3316
- if (auto T = getTypeOfCompletionContextExpr (
3317
- CurrDeclContext->getASTContext (),
3318
- const_cast <DeclContext *>(CurrDeclContext),
3319
- CompletionTypeCheckKind::Normal,
3320
- tempExpr,
3321
- referencedDecl))
3322
- addPostfixOperatorCompletion (op, *T);
3301
+ // TODO: Use referencedDecl (FuncDecl) instead of 'op' (OperatorDecl).
3302
+ addPostfixOperatorCompletion (op, funcTy->getResult ());
3323
3303
}
3324
3304
3325
3305
void addAssignmentOperator (Type RHSType, Type resultType) {
@@ -3366,169 +3346,67 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3366
3346
addTypeAnnotation (builder, resultType);
3367
3347
}
3368
3348
3369
- void tryInfixOperatorCompletion (InfixOperatorDecl *op, SequenceExpr *SE) {
3370
- if (op->getName ().str () == " ~>" )
3371
- return ;
3372
-
3373
- MutableArrayRef<Expr *> sequence = SE->getElements ();
3374
- assert (sequence.size () >= 3 && !sequence.back () &&
3375
- !sequence.drop_back (1 ).back () && " sequence not cleaned up" );
3376
- assert ((sequence.size () & 1 ) && " sequence expr ending with operator" );
3377
-
3378
- // FIXME: these checks should apply to the LHS of the operator, not the
3379
- // immediately left expression. Move under the type-checking.
3380
- Expr *LHS = sequence.drop_back (2 ).back ();
3381
- if (LHS->getType () && (LHS->getType ()->is <MetatypeType>() ||
3382
- LHS->getType ()->is <AnyFunctionType>()))
3349
+ void tryInfixOperatorCompletion (Expr *foldedExpr, InfixOperatorDecl *op) {
3350
+ ConcreteDeclRef referencedDecl;
3351
+ FunctionType *funcTy = getTypeOfCompletionOperator (
3352
+ const_cast <DeclContext *>(CurrDeclContext), foldedExpr, op->getName (),
3353
+ DeclRefKind::BinaryOperator, referencedDecl);
3354
+ if (!funcTy)
3383
3355
return ;
3384
3356
3385
- // Preserve LHS type for restoring it.
3386
- Type LHSTy = LHS->getType ();
3387
-
3388
- // We allocate these expressions on the stack because we know they can't
3389
- // escape and there isn't a better way to allocate scratch Expr nodes.
3390
- UnresolvedDeclRefExpr UDRE (op->getName (), DeclRefKind::BinaryOperator,
3391
- DeclNameLoc (LHS->getEndLoc ()));
3392
- sequence.drop_back (1 ).back () = &UDRE;
3393
- CodeCompletionExpr CCE (LHS->getSourceRange ());
3394
- sequence.back () = &CCE;
3395
-
3396
- SWIFT_DEFER {
3397
- // Reset sequence.
3398
- SE->setElement (SE->getNumElements () - 1 , nullptr );
3399
- SE->setElement (SE->getNumElements () - 2 , nullptr );
3400
- LHS->setType (LHSTy);
3401
- prepareForRetypechecking (SE);
3402
-
3403
- for (auto &element : sequence.drop_back (2 )) {
3404
- // Unfold expressions for re-typechecking sequence.
3405
- if (auto *assignExpr = dyn_cast_or_null<AssignExpr>(element)) {
3406
- assignExpr->setSrc (nullptr );
3407
- assignExpr->setDest (nullptr );
3408
- } else if (auto *ifExpr = dyn_cast_or_null<IfExpr>(element)) {
3409
- ifExpr->setCondExpr (nullptr );
3410
- ifExpr->setElseExpr (nullptr );
3411
- }
3412
-
3413
- // Reset any references to operators in types, so they are properly
3414
- // handled as operators by sequence folding.
3415
- //
3416
- // FIXME: Would be better to have some kind of 'OperatorRefExpr'?
3417
- if (auto operatorRef = element->getMemberOperatorRef ()) {
3418
- operatorRef->setType (nullptr );
3419
- element = operatorRef;
3420
- }
3421
- }
3422
- };
3357
+ Type lhsTy = funcTy->getParams ()[0 ].getPlainType ();
3358
+ Type rhsTy = funcTy->getParams ()[1 ].getPlainType ();
3359
+ Type resultTy = funcTy->getResult ();
3423
3360
3424
- Expr *expr = SE;
3425
- if (!typeCheckCompletionSequence (const_cast <DeclContext *>(CurrDeclContext),
3426
- expr)) {
3427
- if (!LHS->getType () ||
3428
- !LHS->getType ()->getRValueType ()->getOptionalObjectType ()) {
3429
- // Don't complete optional operators on non-optional types.
3430
- // FIXME: can we get the type-checker to disallow these for us?
3431
- if (op->getName ().str () == " ??" )
3361
+ // Don't complete optional operators on non-optional types.
3362
+ if (!lhsTy->getRValueType ()->getOptionalObjectType ()) {
3363
+ // 'T ?? T'
3364
+ if (op->getName ().str () == " ??" )
3365
+ return ;
3366
+ // 'T == nil'
3367
+ if (auto NT = rhsTy->getNominalOrBoundGenericNominal ())
3368
+ if (NT->getName () ==
3369
+ CurrDeclContext->getASTContext ().Id_OptionalNilComparisonType )
3432
3370
return ;
3433
- if (auto NT = CCE.getType ()->getNominalOrBoundGenericNominal ()) {
3434
- if (NT->getName () ==
3435
- CurrDeclContext->getASTContext ().Id_OptionalNilComparisonType )
3436
- return ;
3437
- }
3438
- }
3371
+ }
3439
3372
3440
- // If the right-hand side and result type are both type parameters, we're
3441
- // not providing a useful completion.
3442
- if (expr->getType ()->isTypeParameter () &&
3443
- CCE.getType ()->isTypeParameter ())
3444
- return ;
3373
+ // If the right-hand side and result type are both type parameters, we're
3374
+ // not providing a useful completion.
3375
+ if (resultTy->isTypeParameter () && rhsTy->isTypeParameter ())
3376
+ return ;
3445
3377
3446
- addInfixOperatorCompletion (op, expr->getType (), CCE.getType ());
3447
- }
3448
- }
3449
-
3450
- void flattenBinaryExpr (Expr *expr, SmallVectorImpl<Expr *> &sequence) {
3451
- if (auto binExpr = dyn_cast<BinaryExpr>(expr)) {
3452
- flattenBinaryExpr (binExpr->getArg ()->getElement (0 ), sequence);
3453
- sequence.push_back (binExpr->getFn ());
3454
- flattenBinaryExpr (binExpr->getArg ()->getElement (1 ), sequence);
3455
- } else if (auto assignExpr = dyn_cast<AssignExpr>(expr)) {
3456
- flattenBinaryExpr (assignExpr->getDest (), sequence);
3457
- sequence.push_back (assignExpr);
3458
- flattenBinaryExpr (assignExpr->getSrc (), sequence);
3459
- assignExpr->setDest (nullptr );
3460
- assignExpr->setSrc (nullptr );
3461
- } else if (auto ifExpr = dyn_cast<IfExpr>(expr)) {
3462
- flattenBinaryExpr (ifExpr->getCondExpr (), sequence);
3463
- sequence.push_back (ifExpr);
3464
- flattenBinaryExpr (ifExpr->getElseExpr (), sequence);
3465
- ifExpr->setCondExpr (nullptr );
3466
- ifExpr->setElseExpr (nullptr );
3467
- } else if (auto tryExpr = dyn_cast<AnyTryExpr>(expr)) {
3468
- // Strip out try expression. It doesn't affect completion.
3469
- flattenBinaryExpr (tryExpr->getSubExpr (), sequence);
3470
- } else if (auto optEval = dyn_cast<OptionalEvaluationExpr>(expr)){
3471
- // Strip out optional evaluation expression. It doesn't affect completion.
3472
- flattenBinaryExpr (optEval->getSubExpr (), sequence);
3473
- } else {
3474
- sequence.push_back (expr);
3475
- }
3378
+ // TODO: Use referencedDecl (FuncDecl) instead of 'op' (OperatorDecl).
3379
+ addInfixOperatorCompletion (op, funcTy->getResult (),
3380
+ funcTy->getParams ()[1 ].getPlainType ());
3476
3381
}
3477
3382
3478
- void typeCheckLeadingSequence (SmallVectorImpl<Expr *> &sequence) {
3383
+ Expr *typeCheckLeadingSequence (Expr *LHS, ArrayRef<Expr *> leadingSequence) {
3384
+ if (leadingSequence.empty ())
3385
+ return LHS;
3479
3386
3480
- // Strip out try and optional evaluation expr because foldSequence() mutates
3481
- // hierarchy of these expressions. They don't affect completion anyway.
3482
- for (auto &element : sequence) {
3483
- if (auto *tryExpr = dyn_cast<AnyTryExpr>(element))
3484
- element = tryExpr->getSubExpr ();
3485
- if (auto *optEval = dyn_cast<OptionalEvaluationExpr>(element))
3486
- element = optEval->getSubExpr ();
3487
- }
3387
+ assert (leadingSequence.size () % 2 == 0 );
3388
+ SmallVector<Expr *, 3 > sequence (leadingSequence.begin (),
3389
+ leadingSequence.end ());
3390
+ sequence.push_back (LHS);
3488
3391
3489
3392
Expr *expr =
3490
3393
SequenceExpr::create (CurrDeclContext->getASTContext (), sequence);
3491
3394
prepareForRetypechecking (expr);
3492
- // Take advantage of the fact the type-checker leaves the types on the AST.
3493
3395
if (!typeCheckExpression (const_cast <DeclContext *>(CurrDeclContext),
3494
3396
expr)) {
3495
- // Rebuild the sequence from the type-checked version.
3496
- sequence.clear ();
3497
- flattenBinaryExpr (expr, sequence);
3498
- return ;
3397
+ return expr;
3499
3398
}
3500
-
3501
- // Fall back to just using the immediate LHS.
3502
- auto LHS = sequence.back ();
3503
- sequence.clear ();
3504
- sequence.push_back (LHS);
3399
+ return LHS;
3505
3400
}
3506
3401
3507
3402
void getOperatorCompletions (Expr *LHS, ArrayRef<Expr *> leadingSequence) {
3508
- std::vector<OperatorDecl *> operators = collectOperators ( );
3403
+ Expr *foldedExpr = typeCheckLeadingSequence (LHS, leadingSequence );
3509
3404
3405
+ std::vector<OperatorDecl *> operators = collectOperators ();
3510
3406
// FIXME: this always chooses the first operator with the given name.
3511
3407
llvm::DenseSet<Identifier> seenPostfixOperators;
3512
3408
llvm::DenseSet<Identifier> seenInfixOperators;
3513
3409
3514
- SmallVector<Expr *, 3 > sequence (leadingSequence.begin (),
3515
- leadingSequence.end ());
3516
- sequence.push_back (LHS);
3517
- assert ((sequence.size () & 1 ) && " sequence expr ending with operator" );
3518
-
3519
- if (sequence.size () > 1 )
3520
- typeCheckLeadingSequence (sequence);
3521
-
3522
- // Retrieve typechecked LHS.
3523
- LHS = sequence.back ();
3524
-
3525
- // Create a single sequence expression, which we will modify for each
3526
- // operator, filling in the operator and dummy right-hand side.
3527
- sequence.push_back (nullptr ); // operator
3528
- sequence.push_back (nullptr ); // RHS
3529
- auto *SE = SequenceExpr::create (CurrDeclContext->getASTContext (), sequence);
3530
- prepareForRetypechecking (SE);
3531
-
3532
3410
for (auto op : operators) {
3533
3411
switch (op->getKind ()) {
3534
3412
case DeclKind::PrefixOperator:
@@ -3541,7 +3419,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3541
3419
break ;
3542
3420
case DeclKind::InfixOperator:
3543
3421
if (seenInfixOperators.insert (op->getName ()).second )
3544
- tryInfixOperatorCompletion (cast<InfixOperatorDecl>(op), SE );
3422
+ tryInfixOperatorCompletion (foldedExpr, cast<InfixOperatorDecl>(op));
3545
3423
break ;
3546
3424
default :
3547
3425
llvm_unreachable (" unexpected operator kind" );
0 commit comments