1818#include " TypeChecker.h"
1919#include " MiscDiagnostics.h"
2020#include " swift/AST/ASTWalker.h"
21+ #include " swift/AST/Initializer.h"
2122#include " swift/AST/NameLookup.h"
2223#include " swift/AST/Pattern.h"
2324#include " swift/AST/TypeRefinementContext.h"
@@ -856,27 +857,41 @@ static Optional<ASTNode> findInnermostAncestor(
856857static const Decl *findContainingDeclaration (SourceRange ReferenceRange,
857858 const DeclContext *ReferenceDC,
858859 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+ }
860877 return D;
878+ }
861879
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.
868885 if (ReferenceRange.isInvalid ())
869886 return nullptr ;
870887
871888 SourceFile *SF = ReferenceDC->getParentSourceFile ();
872889 if (!SF)
873890 return nullptr ;
874891
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;
880895
881896 return nullptr ;
882897}
@@ -929,9 +944,13 @@ abstractSyntaxDeclForAvailableAttribute(const Decl *ConcreteSyntaxDecl) {
929944 // binding.
930945 ArrayRef<PatternBindingEntry> Entries = PBD->getPatternList ();
931946 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;
935954 }
936955 } else if (auto *ECD = dyn_cast<EnumCaseDecl>(ConcreteSyntaxDecl)) {
937956 // Similar to the PatternBindingDecl case above, we return the
@@ -1091,35 +1110,17 @@ static void findAvailabilityFixItNodes(SourceRange ReferenceRange,
10911110 FoundVersionCheckNode =
10921111 findInnermostAncestor (ReferenceRange, SM, SearchRoot, IsGuardable);
10931112
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-
11121113 // Try to find declarations on which @available attributes can be added.
11131114 // The heuristics for finding these declarations are biased towards deeper
11141115 // nodes in the AST to limit the scope of suggested availability regions
11151116 // and provide a better IDE experience (it can get jumpy if Fix-It locations
11161117 // are far away from the error needing the Fix-It).
1117- if (ContainingDecl ) {
1118+ if (DeclarationToSearch ) {
11181119 FoundMemberLevelDecl =
1119- ancestorMemberLevelDeclForAvailabilityFixit (ContainingDecl );
1120+ ancestorMemberLevelDeclForAvailabilityFixit (DeclarationToSearch );
11201121
11211122 FoundTypeLevelDecl =
1122- ancestorTypeLevelDeclForAvailabilityFixit (ContainingDecl );
1123+ ancestorTypeLevelDeclForAvailabilityFixit (DeclarationToSearch );
11231124 }
11241125}
11251126
@@ -1408,7 +1409,7 @@ someEnclosingDeclMatches(SourceRange ReferenceRange,
14081409 // Climb the DeclContext hierarchy to see if any of the containing
14091410 // declarations matches the predicate.
14101411 const DeclContext *DC = ReferenceDC;
1411- do {
1412+ while ( true ) {
14121413 auto *D = DC->getInnermostDeclarationDeclContext ();
14131414 if (!D)
14141415 break ;
@@ -1424,20 +1425,15 @@ someEnclosingDeclMatches(SourceRange ReferenceRange,
14241425 return true ;
14251426 }
14261427
1427- DC = DC-> getParent ();
1428- } while (DC);
1428+ DC = D-> getDeclContext ();
1429+ }
14291430
14301431 // Search the AST starting from our innermost declaration context to see if
14311432 // if the reference is inside a property declaration but not inside an
14321433 // accessor (this can happen for the TypeRepr for the declared type of a
14331434 // property, for example).
14341435 // 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.
14411437
14421438 // Don't search for a containing declaration if we don't have a source range.
14431439 if (ReferenceRange.isInvalid ())
@@ -1448,28 +1444,11 @@ someEnclosingDeclMatches(SourceRange ReferenceRange,
14481444 findContainingDeclaration (ReferenceRange, ReferenceDC, Ctx.SourceMgr );
14491445
14501446 // 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).
14521448 if (!DeclToSearch)
14531449 return false ;
14541450
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));
14731452}
14741453
14751454// / Returns true if the reference or any of its parents is an
0 commit comments