@@ -1813,6 +1813,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
1813
1813
bool PreferFunctionReferencesToCalls = false ;
1814
1814
bool HaveLeadingSpace = false ;
1815
1815
1816
+ bool CheckForDuplicates = false ;
1817
+ llvm::DenseSet<std::pair<const Decl *, Type>> PreviouslySeen;
1818
+
1816
1819
bool IncludeInstanceMembers = false ;
1817
1820
1818
1821
// / True if we are code completing inside a static method.
@@ -1998,6 +2001,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
1998
2001
IsKeyPathExpr = true ;
1999
2002
}
2000
2003
2004
+ void shouldCheckForDuplicates (bool value = true ) {
2005
+ CheckForDuplicates = value;
2006
+ }
2007
+
2001
2008
void setIsSwiftKeyPathExpr (bool onRoot) {
2002
2009
IsSwiftKeyPathExpr = true ;
2003
2010
IsAfterSwiftKeyPathRoot = onRoot;
@@ -2895,8 +2902,13 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2895
2902
IsImplicitlyCurriedInstanceMethod = isImplicitlyCurriedInstanceMethod (FD);
2896
2903
2897
2904
// Strip off '(_ self: Self)' if needed.
2898
- if (AFT && !IsImplicitlyCurriedInstanceMethod)
2905
+ if (AFT && !IsImplicitlyCurriedInstanceMethod) {
2899
2906
AFT = AFT->getResult ()->getAs <AnyFunctionType>();
2907
+
2908
+ // Check for duplicates with the adjusted type too.
2909
+ if (isDuplicate (FD, AFT))
2910
+ return ;
2911
+ }
2900
2912
}
2901
2913
2902
2914
bool trivialTrailingClosure = false ;
@@ -3369,10 +3381,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3369
3381
DynamicLookupInfo dynamicLookupInfo) {
3370
3382
auto funcTy =
3371
3383
getTypeOfMember (AFD, dynamicLookupInfo)->getAs <AnyFunctionType>();
3372
- if (funcTy && AFD->getDeclContext ()->isTypeContext () &&
3373
- !isImplicitlyCurriedInstanceMethod (AFD)) {
3384
+ bool dropCurryLevel = funcTy && AFD->getDeclContext ()->isTypeContext () &&
3385
+ !isImplicitlyCurriedInstanceMethod (AFD);
3386
+ if (dropCurryLevel)
3374
3387
funcTy = funcTy->getResult ()->getAs <AnyFunctionType>();
3375
- }
3376
3388
3377
3389
bool useFunctionReference = PreferFunctionReferencesToCalls;
3378
3390
if (!useFunctionReference && funcTy) {
@@ -3384,6 +3396,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3384
3396
if (!useFunctionReference)
3385
3397
return false ;
3386
3398
3399
+ // Check for duplicates with the adjusted type too.
3400
+ if (dropCurryLevel && isDuplicate (AFD, funcTy))
3401
+ return true ;
3402
+
3387
3403
CommandWordsPairs Pairs;
3388
3404
CodeCompletionResultBuilder Builder (
3389
3405
Sink, CodeCompletionResult::ResultKind::Declaration,
@@ -3421,6 +3437,29 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3421
3437
return true ;
3422
3438
}
3423
3439
3440
+ private:
3441
+
3442
+ // / Returns true if duplicate checking is enabled (via
3443
+ // / \c shouldCheckForDuplicates) and this decl + type combination has been
3444
+ // / checked previously. Returns false otherwise.
3445
+ bool isDuplicate (const ValueDecl *D, Type Ty) {
3446
+ if (!CheckForDuplicates)
3447
+ return false ;
3448
+ return !PreviouslySeen.insert ({D, Ty}).second ;
3449
+ }
3450
+
3451
+ // / Returns true if duplicate checking is enabled (via
3452
+ // / \c shouldCheckForDuplicates) and this decl has been checked previously
3453
+ // / with the type according to \c getTypeOfMember. Returns false otherwise.
3454
+ bool isDuplicate (const ValueDecl *D, DynamicLookupInfo dynamicLookupInfo) {
3455
+ if (!CheckForDuplicates)
3456
+ return false ;
3457
+ Type Ty = getTypeOfMember (D, dynamicLookupInfo);
3458
+ return !PreviouslySeen.insert ({D, Ty}).second ;
3459
+ }
3460
+
3461
+ public:
3462
+
3424
3463
// Implement swift::VisibleDeclConsumer.
3425
3464
void foundDecl (ValueDecl *D, DeclVisibilityKind Reason,
3426
3465
DynamicLookupInfo dynamicLookupInfo) override {
@@ -3436,6 +3475,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3436
3475
3437
3476
if (IsSwiftKeyPathExpr && !SwiftKeyPathFilter (D, Reason))
3438
3477
return ;
3478
+
3479
+ // If we've seen this decl+type before (possible when multiple lookups are
3480
+ // performed e.g. because of ambiguous base types), bail.
3481
+ if (isDuplicate (D, dynamicLookupInfo))
3482
+ return ;
3439
3483
3440
3484
// FIXME(InterfaceTypeRequest): Remove this.
3441
3485
(void )D->getInterfaceType ();
@@ -3526,6 +3570,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3526
3570
Type funcType = getTypeOfMember (FD, dynamicLookupInfo)
3527
3571
->castTo <AnyFunctionType>()
3528
3572
->getResult ();
3573
+
3574
+ // Check for duplicates with the adjusted type too.
3575
+ if (isDuplicate (FD, funcType))
3576
+ return ;
3577
+
3529
3578
addFunctionCallPattern (
3530
3579
funcType->castTo <AnyFunctionType>(), FD,
3531
3580
getSemanticContext (FD, Reason, dynamicLookupInfo));
@@ -6039,6 +6088,7 @@ void deliverDotExprResults(
6039
6088
Lookup.setPreferFunctionReferencesToCalls ();
6040
6089
}
6041
6090
6091
+ Lookup.shouldCheckForDuplicates (Results.size () > 1 );
6042
6092
for (auto &Result: Results) {
6043
6093
Lookup.setIsStaticMetatype (Result.BaseIsStaticMetaType );
6044
6094
Lookup.getPostfixKeywordCompletions (Result.BaseTy , BaseExpr);
0 commit comments