@@ -1438,6 +1438,8 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
14381438#define TYPEREPR (Id, Parent ) bool visit##Id##TypeRepr(Id##TypeRepr *T);
14391439#include " swift/AST/TypeReprNodes.def"
14401440
1441+ bool visitDeclRefTypeRepr (DeclRefTypeRepr *T);
1442+
14411443 using Action = ASTWalker::Action;
14421444
14431445 using PreWalkAction = ASTWalker::PreWalkAction;
@@ -1624,9 +1626,24 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
16241626 return false ;
16251627 }
16261628
1629+ private:
1630+ // / Walk a `MemberTypeRepr` in source order such that each subsequent
1631+ // / dot-separated component is a child of the previous one
1632+ [[nodiscard]] bool doItInSourceOrderRecursive (MemberTypeRepr *T);
1633+
1634+ public:
16271635 // / Returns true on failure.
16281636 [[nodiscard]]
16291637 bool doIt (TypeRepr *T) {
1638+ if (auto *MTR = dyn_cast<MemberTypeRepr>(T)) {
1639+ switch (Walker.getMemberTypeReprWalkingScheme ()) {
1640+ case MemberTypeReprWalkingScheme::SourceOrderRecursive:
1641+ return doItInSourceOrderRecursive (MTR);
1642+ case MemberTypeReprWalkingScheme::ASTOrderRecursive:
1643+ break ;
1644+ }
1645+ }
1646+
16301647 return traverse (
16311648 Walker.walkToTypeReprPre (T),
16321649 [&]() { return visit (T); },
@@ -1706,6 +1723,89 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
17061723
17071724} // end anonymous namespace
17081725
1726+ bool Traversal::doItInSourceOrderRecursive (MemberTypeRepr *T) {
1727+ // Qualified types are modeled resursively such that each previous
1728+ // dot-separated component is a child of the next one. To walk a member type
1729+ // representation according to
1730+ // `MemberTypeReprWalkingScheme::SourceOrderRecursive`:
1731+
1732+ // 1. Pre-walk the dot-separated components in source order. If asked to skip
1733+ // the children of a given component:
1734+ // 1. Set the depth at which to start post-walking later.
1735+ // 2. Skip its generic arguments and subsequent components.
1736+ std::function<bool (TypeRepr *, std::optional<unsigned > &, unsigned )>
1737+ doItInSourceOrderPre = [&](TypeRepr *T,
1738+ std::optional<unsigned > &StartPostWalkDepth,
1739+ unsigned Depth) {
1740+ if (auto *MemberTR = dyn_cast<MemberTypeRepr>(T)) {
1741+ if (doItInSourceOrderPre (MemberTR->getBase (), StartPostWalkDepth,
1742+ Depth + 1 )) {
1743+ return true ;
1744+ }
1745+
1746+ if (StartPostWalkDepth.has_value ()) {
1747+ return false ;
1748+ }
1749+ }
1750+
1751+ switch (this ->Walker .walkToTypeReprPre (T).Action ) {
1752+ case PreWalkAction::Stop:
1753+ return true ;
1754+ case PreWalkAction::SkipChildren:
1755+ StartPostWalkDepth = Depth;
1756+ return false ;
1757+ case PreWalkAction::SkipNode:
1758+ StartPostWalkDepth = Depth + 1 ;
1759+ return false ;
1760+ case PreWalkAction::Continue:
1761+ break ;
1762+ }
1763+
1764+ if (auto *DeclRefTR = dyn_cast<DeclRefTypeRepr>(T)) {
1765+ for (auto *Arg : DeclRefTR->getGenericArgs ()) {
1766+ if (doIt (Arg)) {
1767+ return true ;
1768+ }
1769+ }
1770+ } else if (visit (T)) {
1771+ return true ;
1772+ }
1773+
1774+ return false ;
1775+ };
1776+
1777+ // 2. Post-walk the components in reverse order, respecting the depth at which
1778+ // to start post-walking if set.
1779+ std::function<bool (TypeRepr *, std::optional<unsigned >, unsigned )>
1780+ doItInSourceOrderPost = [&](TypeRepr *T,
1781+ std::optional<unsigned > StartPostWalkDepth,
1782+ unsigned Depth) {
1783+ if (!StartPostWalkDepth.has_value () || Depth >= *StartPostWalkDepth) {
1784+ switch (this ->Walker .walkToTypeReprPost (T).Action ) {
1785+ case PostWalkAction::Continue:
1786+ break ;
1787+ case PostWalkAction::Stop:
1788+ return true ;
1789+ }
1790+ }
1791+
1792+ if (auto *MemberTR = dyn_cast<MemberTypeRepr>(T)) {
1793+ return doItInSourceOrderPost (MemberTR->getBase (), StartPostWalkDepth,
1794+ Depth + 1 );
1795+ }
1796+
1797+ return false ;
1798+ };
1799+
1800+ std::optional<unsigned > StartPostWalkDepth;
1801+
1802+ if (doItInSourceOrderPre (T, StartPostWalkDepth, 0 )) {
1803+ return true ;
1804+ }
1805+
1806+ return doItInSourceOrderPost (T, StartPostWalkDepth, 0 );
1807+ }
1808+
17091809#pragma mark Statement traversal
17101810Stmt *Traversal::visitBreakStmt (BreakStmt *BS) {
17111811 return BS;
@@ -2130,27 +2230,32 @@ bool Traversal::visitAttributedTypeRepr(AttributedTypeRepr *T) {
21302230 return doIt (T->getTypeRepr ());
21312231}
21322232
2133- bool Traversal::visitSimpleIdentTypeRepr (SimpleIdentTypeRepr *T) {
2134- return false ;
2135- }
2233+ bool Traversal::visitDeclRefTypeRepr (DeclRefTypeRepr *T) {
2234+ if (auto *memberTR = dyn_cast<MemberTypeRepr>(T)) {
2235+ if (doIt (memberTR->getBase ())) {
2236+ return true ;
2237+ }
2238+ }
21362239
2137- bool Traversal::visitGenericIdentTypeRepr (GenericIdentTypeRepr *T) {
2138- for (auto genArg : T->getGenericArgs ()) {
2139- if (doIt (genArg))
2240+ for (auto *genericArg : T->getGenericArgs ()) {
2241+ if (doIt (genericArg)) {
21402242 return true ;
2243+ }
21412244 }
2245+
21422246 return false ;
21432247}
21442248
2145- bool Traversal::visitMemberTypeRepr (MemberTypeRepr *T) {
2146- if ( doIt (T-> getRoot ()))
2147- return true ;
2249+ bool Traversal::visitSimpleIdentTypeRepr (SimpleIdentTypeRepr *T) {
2250+ return visitDeclRefTypeRepr (T);
2251+ }
21482252
2149- for (auto comp : T->getMemberComponents ()) {
2150- if (doIt (comp))
2151- return true ;
2152- }
2153- return false ;
2253+ bool Traversal::visitGenericIdentTypeRepr (GenericIdentTypeRepr *T) {
2254+ return visitDeclRefTypeRepr (T);
2255+ }
2256+
2257+ bool Traversal::visitMemberTypeRepr (MemberTypeRepr *T) {
2258+ return visitDeclRefTypeRepr (T);
21542259}
21552260
21562261bool Traversal::visitFunctionTypeRepr (FunctionTypeRepr *T) {
0 commit comments