18
18
#include " TypeChecker.h"
19
19
#include " MiscDiagnostics.h"
20
20
#include " swift/AST/ASTWalker.h"
21
+ #include " swift/AST/Initializer.h"
21
22
#include " swift/AST/NameLookup.h"
22
23
#include " swift/AST/Pattern.h"
23
24
#include " swift/AST/TypeRefinementContext.h"
@@ -856,27 +857,41 @@ static Optional<ASTNode> findInnermostAncestor(
856
857
static const Decl *findContainingDeclaration (SourceRange ReferenceRange,
857
858
const DeclContext *ReferenceDC,
858
859
const SourceManager &SM) {
859
- if (const Decl *D = ReferenceDC->getInnermostDeclarationDeclContext ())
860
+ auto ContainsReferenceRange = [&](const Decl *D) -> bool {
861
+ if (ReferenceRange.isInvalid ())
862
+ return false ;
863
+ return SM.rangeContains (D->getSourceRange (), ReferenceRange);
864
+ };
865
+
866
+ if (const Decl *D = ReferenceDC->getInnermostDeclarationDeclContext ()) {
867
+ // If we have an inner declaration context, see if we can narrow the search
868
+ // down to one of its members. This is important for properties, which don't
869
+ // count as DeclContexts of their own but which can still introduce
870
+ // availability.
871
+ if (auto *IDC = dyn_cast<IterableDeclContext>(D)) {
872
+ auto BestMember = llvm::find_if (IDC->getMembers (),
873
+ ContainsReferenceRange);
874
+ if (BestMember != IDC->getMembers ().end ())
875
+ return *BestMember;
876
+ }
860
877
return D;
878
+ }
861
879
862
- // We couldn't find a suitable node by climbing the DeclContext
863
- // hierarchy, so fall back to looking for a top-level declaration
864
- // that contains the reference range. We will hit this case for
865
- // top-level elements that do not themselves introduce DeclContexts,
866
- // such as extensions and global variables. If we don't have a reference
867
- // range, there is nothing we can do, so return null.
880
+ // We couldn't find a suitable node by climbing the DeclContext hierarchy, so
881
+ // fall back to looking for a top-level declaration that contains the
882
+ // reference range. We will hit this case for top-level elements that do not
883
+ // themselves introduce DeclContexts, such as global variables. If we don't
884
+ // have a reference range, there is nothing we can do, so return null.
868
885
if (ReferenceRange.isInvalid ())
869
886
return nullptr ;
870
887
871
888
SourceFile *SF = ReferenceDC->getParentSourceFile ();
872
889
if (!SF)
873
890
return nullptr ;
874
891
875
- for (Decl *D : SF->Decls ) {
876
- if (SM.rangeContains (D->getSourceRange (), ReferenceRange)) {
877
- return D;
878
- }
879
- }
892
+ auto BestTopLevelDecl = llvm::find_if (SF->Decls , ContainsReferenceRange);
893
+ if (BestTopLevelDecl != SF->Decls .end ())
894
+ return *BestTopLevelDecl;
880
895
881
896
return nullptr ;
882
897
}
@@ -929,9 +944,13 @@ abstractSyntaxDeclForAvailableAttribute(const Decl *ConcreteSyntaxDecl) {
929
944
// binding.
930
945
ArrayRef<PatternBindingEntry> Entries = PBD->getPatternList ();
931
946
if (!Entries.empty ()) {
932
- VarDecl *VD = Entries.front ().getPattern ()->getSingleVar ();
933
- if (VD)
934
- return VD;
947
+ const VarDecl *AnyVD = nullptr ;
948
+ // FIXME: This is wasteful; we only need the first variable.
949
+ Entries.front ().getPattern ()->forEachVariable ([&](const VarDecl *VD) {
950
+ AnyVD = VD;
951
+ });
952
+ if (AnyVD)
953
+ return AnyVD;
935
954
}
936
955
} else if (auto *ECD = dyn_cast<EnumCaseDecl>(ConcreteSyntaxDecl)) {
937
956
// Similar to the PatternBindingDecl case above, we return the
@@ -1091,35 +1110,17 @@ static void findAvailabilityFixItNodes(SourceRange ReferenceRange,
1091
1110
FoundVersionCheckNode =
1092
1111
findInnermostAncestor (ReferenceRange, SM, SearchRoot, IsGuardable);
1093
1112
1094
- // Find some Decl that contains the reference range. We use this declaration
1095
- // as a starting place to climb the DeclContext hierarchy to find
1096
- // places to suggest adding @available() annotations.
1097
- InnermostAncestorFinder::MatchPredicate IsDeclaration = [](
1098
- ASTNode Node, ASTWalker::ParentTy Parent) { return Node.is <Decl *>(); };
1099
-
1100
- Optional<ASTNode> FoundDeclarationNode =
1101
- findInnermostAncestor (ReferenceRange, SM, SearchRoot, IsDeclaration);
1102
-
1103
- const Decl *ContainingDecl = nullptr ;
1104
- if (FoundDeclarationNode.hasValue ()) {
1105
- ContainingDecl = FoundDeclarationNode.getValue ().get <Decl *>();
1106
- }
1107
-
1108
- if (!ContainingDecl) {
1109
- ContainingDecl = ReferenceDC->getInnermostMethodContext ();
1110
- }
1111
-
1112
1113
// Try to find declarations on which @available attributes can be added.
1113
1114
// The heuristics for finding these declarations are biased towards deeper
1114
1115
// nodes in the AST to limit the scope of suggested availability regions
1115
1116
// and provide a better IDE experience (it can get jumpy if Fix-It locations
1116
1117
// are far away from the error needing the Fix-It).
1117
- if (ContainingDecl ) {
1118
+ if (DeclarationToSearch ) {
1118
1119
FoundMemberLevelDecl =
1119
- ancestorMemberLevelDeclForAvailabilityFixit (ContainingDecl );
1120
+ ancestorMemberLevelDeclForAvailabilityFixit (DeclarationToSearch );
1120
1121
1121
1122
FoundTypeLevelDecl =
1122
- ancestorTypeLevelDeclForAvailabilityFixit (ContainingDecl );
1123
+ ancestorTypeLevelDeclForAvailabilityFixit (DeclarationToSearch );
1123
1124
}
1124
1125
}
1125
1126
@@ -1408,7 +1409,7 @@ someEnclosingDeclMatches(SourceRange ReferenceRange,
1408
1409
// Climb the DeclContext hierarchy to see if any of the containing
1409
1410
// declarations matches the predicate.
1410
1411
const DeclContext *DC = ReferenceDC;
1411
- do {
1412
+ while ( true ) {
1412
1413
auto *D = DC->getInnermostDeclarationDeclContext ();
1413
1414
if (!D)
1414
1415
break ;
@@ -1424,20 +1425,15 @@ someEnclosingDeclMatches(SourceRange ReferenceRange,
1424
1425
return true ;
1425
1426
}
1426
1427
1427
- DC = DC-> getParent ();
1428
- } while (DC);
1428
+ DC = D-> getDeclContext ();
1429
+ }
1429
1430
1430
1431
// Search the AST starting from our innermost declaration context to see if
1431
1432
// if the reference is inside a property declaration but not inside an
1432
1433
// accessor (this can happen for the TypeRepr for the declared type of a
1433
1434
// property, for example).
1434
1435
// We can't rely on the DeclContext hierarchy climb above because properties
1435
- // do not introduce a new DeclContext. This search is potentially slow, so we
1436
- // do it last and only if the reference declaration context is a
1437
- // type or global context.
1438
-
1439
- if (!ReferenceDC->isTypeContext () && !ReferenceDC->isModuleScopeContext ())
1440
- return false ;
1436
+ // do not introduce a new DeclContext.
1441
1437
1442
1438
// Don't search for a containing declaration if we don't have a source range.
1443
1439
if (ReferenceRange.isInvalid ())
@@ -1448,28 +1444,11 @@ someEnclosingDeclMatches(SourceRange ReferenceRange,
1448
1444
findContainingDeclaration (ReferenceRange, ReferenceDC, Ctx.SourceMgr );
1449
1445
1450
1446
// We may not be able to find a declaration to search if the ReferenceRange
1451
- // is invalid (i.e., we are in synthesized code).
1447
+ // isn't useful (i.e., we are in synthesized code).
1452
1448
if (!DeclToSearch)
1453
1449
return false ;
1454
1450
1455
- InnermostAncestorFinder::MatchPredicate IsDeclaration =
1456
- [](ASTNode Node, ASTWalker::ParentTy Parent) {
1457
- return Node.is <Decl *>();
1458
- };
1459
-
1460
- Optional<ASTNode> FoundDeclarationNode =
1461
- findInnermostAncestor (ReferenceRange, Ctx.SourceMgr ,
1462
- const_cast <Decl *>(DeclToSearch), IsDeclaration);
1463
-
1464
- if (FoundDeclarationNode.hasValue ()) {
1465
- const Decl *D = FoundDeclarationNode.getValue ().get <Decl *>();
1466
- D = abstractSyntaxDeclForAvailableAttribute (D);
1467
- if (Pred (D)) {
1468
- return true ;
1469
- }
1470
- }
1471
-
1472
- return false ;
1451
+ return Pred (abstractSyntaxDeclForAvailableAttribute (DeclToSearch));
1473
1452
}
1474
1453
1475
1454
// / Returns true if the reference or any of its parents is an
0 commit comments