@@ -670,8 +670,13 @@ std::pair<bool, Expr *> ModelASTWalker::walkToExprPre(Expr *E) {
670
670
// from the `VarDecl` and the `PatternBindingDecl` entries.
671
671
// We take over visitation here to avoid walking the `PatternBindingDecl` ones.
672
672
for (auto c : CLE->getCaptureList ()) {
673
- if (auto *VD = c.Var )
673
+ if (auto *VD = c.Var ) {
674
+ // We're skipping over the PatternBindingDecl so we need to handle the
675
+ // the VarDecl's attributes that we'd normally process visiting the PBD.
676
+ if (!handleAttrs (VD->getAttrs ()))
677
+ return { false , nullptr };
674
678
VD->walk (*this );
679
+ }
675
680
}
676
681
if (auto *CE = CLE->getClosureBody ())
677
682
CE->walk (*this );
@@ -862,8 +867,14 @@ bool ModelASTWalker::walkToDeclPre(Decl *D) {
862
867
if (D->isImplicit ())
863
868
return false ;
864
869
865
- if (!handleAttrs (D->getAttrs ()))
866
- return false ;
870
+ // The attributes of EnumElementDecls and VarDecls are handled when visiting
871
+ // their parent EnumCaseDecl/PatternBindingDecl (which the attributes are
872
+ // attached to syntactically).
873
+ if (!isa<EnumElementDecl>(D) &&
874
+ !(isa<VarDecl>(D) && cast<VarDecl>(D)->getParentPatternBinding ())) {
875
+ if (!handleAttrs (D->getAttrs ()))
876
+ return false ;
877
+ }
867
878
868
879
if (isa<AccessorDecl>(D)) {
869
880
// Don't push structure nodes for accessors.
@@ -948,6 +959,21 @@ bool ModelASTWalker::walkToDeclPre(Decl *D) {
948
959
SN.TypeRange = charSourceRangeFromSourceRange (SM,
949
960
PD->getTypeSourceRangeForDiagnostics ());
950
961
pushStructureNode (SN, PD);
962
+ } else if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
963
+ // Process the attributes of one of the contained VarDecls. Attributes that
964
+ // are syntactically attached to the PatternBindingDecl end up on the
965
+ // contained VarDecls.
966
+ VarDecl *Contained = nullptr ;
967
+ for (auto idx : range (PBD->getNumPatternEntries ())) {
968
+ PBD->getPattern (idx)->forEachVariable ([&](VarDecl *VD) -> void {
969
+ Contained = VD;
970
+ });
971
+ if (Contained) {
972
+ if (!handleAttrs (Contained->getAttrs ()))
973
+ return false ;
974
+ break ;
975
+ }
976
+ }
951
977
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
952
978
const DeclContext *DC = VD->getDeclContext ();
953
979
SyntaxStructureNode SN;
@@ -1012,15 +1038,9 @@ bool ModelASTWalker::walkToDeclPre(Decl *D) {
1012
1038
1013
1039
// We need to handle the special case where attributes semantically
1014
1040
// attach to enum element decls while syntactically locate before enum case decl.
1015
- for (auto *EnumElemD : EnumCaseD->getElements ()) {
1016
- for (auto *Att : EnumElemD->getAttrs ()) {
1017
- if (Att->isDeclModifier () &&
1018
- SM.isBeforeInBuffer (Att->getLocation (), D->getSourceRange ().Start )) {
1019
- passNonTokenNode ({SyntaxNodeKind::AttributeBuiltin,
1020
- charSourceRangeFromSourceRange (SM,
1021
- Att->getLocation ())});
1022
- }
1023
- }
1041
+ if (!EnumCaseD->getElements ().empty ()) {
1042
+ if (!handleAttrs (EnumCaseD->getElements ().front ()->getAttrs ()))
1043
+ return false ;
1024
1044
}
1025
1045
if (pushStructureNode (SN, D)) {
1026
1046
// FIXME: ASTWalker walks enum elements as members of the enum decl, not
0 commit comments