18
18
#include " swift/AST/AccessNotes.h"
19
19
#include " swift/AST/Attr.h"
20
20
#include " swift/AST/Decl.h"
21
+ #include " swift/AST/Module.h" // DeclContext::isModuleScopeContext()
21
22
#include " swift/Parse/Parser.h"
22
23
#include " llvm/ADT/STLExtras.h"
23
24
#include " llvm/ADT/StringRef.h"
@@ -61,39 +62,87 @@ parseObjCSelector(swift::ASTContext &ctx, llvm::StringRef string) {
61
62
62
63
namespace swift {
63
64
64
- NullablePtr<const AccessNote> AccessNotes::lookup (ValueDecl *VD) const {
65
- assert (VD != nullptr );
65
+ AccessNoteDeclName::AccessNoteDeclName () : parentNames(), name() { }
66
+
67
+ AccessNoteDeclName::AccessNoteDeclName (ASTContext &ctx, StringRef str) {
68
+ auto parsedName = parseDeclName (str);
69
+
70
+ StringRef first, rest = parsedName.ContextName ;
71
+ while (!rest.empty ()) {
72
+ std::tie (first, rest) = rest.split (' .' );
73
+ parentNames.push_back (ctx.getIdentifier (first));
74
+ }
75
+
76
+ name = parsedName.formDeclName (ctx);
77
+
78
+ // FIXME: parseDeclName() doesn't handle the special `subscript` name.
79
+ // Fixing this without affecting existing uses in import-as-member will need
80
+ // a bit of work. Hack around the problem for this specific caller instead.
81
+ if (name.getBaseName () == ctx.getIdentifier (" subscript" ))
82
+ name = DeclName (ctx, DeclBaseName::createSubscript (),
83
+ name.getArgumentNames ());
84
+ }
66
85
86
+ bool AccessNoteDeclName::matches (ValueDecl *VD) const {
67
87
auto lookupVD = VD;
68
88
if (auto accessor = dyn_cast<AccessorDecl>(VD))
69
89
VD = accessor->getStorage ();
70
90
71
- auto lookupName = lookupVD->getName ();
91
+ if (!lookupVD->getName ().matchesRef (name))
92
+ return false ;
72
93
73
- // FIXME: parseDeclName() doesn't handle the special `subscript` name .
74
- // Fixing this without affecting existing uses in import-as-member will need
75
- // a bit of work. Hack around this by changing to a normal identifier.
76
- if (isa<SubscriptDecl>(lookupVD) &&
77
- lookupName. getBaseName () == DeclBaseName::createSubscript ()) {
78
- ASTContext &ctx = lookupVD-> getASTContext ();
79
- lookupName = DeclName (ctx, ctx. getIdentifier ( " subscript " ),
80
- lookupName. getArgumentNames ());
81
- }
94
+ // The rest of this checks `parentNames` against the parents of `lookupVD` .
95
+
96
+ ArrayRef<Identifier> remainingContextNames = parentNames;
97
+ DeclContext *nextContext = lookupVD-> getDeclContext ();
98
+
99
+ while (!nextContext-> isModuleScopeContext ()) {
100
+ // If we've run out of names without reaching module scope, we've failed.
101
+ if (remainingContextNames. empty ())
102
+ return false ;
82
103
83
- const std::vector<AccessNote> *notesToSearch = ¬es ;
104
+ Identifier contextName = remainingContextNames. back () ;
84
105
85
- // If nested, look at the parent context's notes.
86
- if (auto parent = lookupVD->getDeclContext ()->getSelfNominalTypeDecl ()) {
87
- if (auto parentNote = lookup (parent))
88
- notesToSearch = &(parentNote.get ()->members );
89
- else
90
- return nullptr ;
106
+ // If the context is not a type (or extension), we can't name VD in an
107
+ // access note and the match fails; if the name doesn't match, the match
108
+ // fails too.
109
+ auto contextType = nextContext->getSelfNominalTypeDecl ();
110
+ if (!contextType || contextType->getName () != contextName)
111
+ return false ;
112
+
113
+ // Still checking. Move to the parent.
114
+ remainingContextNames = remainingContextNames.drop_back ();
115
+ nextContext = contextType->getParent ();
91
116
}
92
117
93
- auto iter = llvm::find_if (*notesToSearch, [&](const AccessNote ¬e) -> bool {
94
- return lookupName.matchesRef (note.name );
118
+ // If the context is module-scoped, we've succeeded if we're out of names, or
119
+ // failed if we still have some names to go.
120
+ return remainingContextNames.empty ();
121
+ }
122
+
123
+ bool AccessNoteDeclName::empty () const {
124
+ return !name;
125
+ }
126
+
127
+ void AccessNoteDeclName::print (llvm::raw_ostream &os) const {
128
+ for (auto parentName : parentNames)
129
+ os << parentName << ' .' ;
130
+ name.print (os, /* skipEmptyArgumentNames=*/ false );
131
+ }
132
+
133
+ void AccessNoteDeclName::dump () const {
134
+ print (llvm::errs ());
135
+ llvm::errs () << ' \n ' ;
136
+ }
137
+
138
+ NullablePtr<const AccessNote> AccessNotes::lookup (ValueDecl *VD) const {
139
+ assert (VD != nullptr );
140
+
141
+ auto iter = llvm::find_if (notes, [&](const AccessNote ¬e) -> bool {
142
+ return note.name .matches (VD);
95
143
});
96
- return NullablePtr<const AccessNote>(iter == notesToSearch->end () ? nullptr : &*iter);
144
+
145
+ return NullablePtr<const AccessNote>(iter == notes.end () ? nullptr : &*iter);
97
146
}
98
147
99
148
void AccessNotes::dump () const {
@@ -114,8 +163,11 @@ void AccessNotes::dump(llvm::raw_ostream &os) const {
114
163
}
115
164
116
165
void AccessNote::dump (llvm::raw_ostream &os, int indent) const {
117
- os.indent (indent) << " (note name='" << name << " '" ;
118
- if (name.getBaseName ().isSpecial ())
166
+ os.indent (indent) << " (note name='" ;
167
+ name.print (os);
168
+ os << " '" ;
169
+
170
+ if (name.name .getBaseName ().isSpecial ())
119
171
os << " is_special_name" ;
120
172
121
173
if (ObjC)
@@ -125,22 +177,12 @@ void AccessNote::dump(llvm::raw_ostream &os, int indent) const {
125
177
if (Dynamic)
126
178
os << " dynamic=" << *Dynamic;
127
179
128
- if (!members.empty ()) {
129
- os << " \n " ;
130
- os.indent (indent + 2 ) << " (members" ;
131
- for (const auto &member : members) {
132
- os << " \n " ;
133
- member.dump (os, indent + 4 );
134
- }
135
- os << " )" ;
136
- }
137
-
138
180
os << " )" ;
139
181
}
140
182
141
183
}
142
184
143
- LLVM_YAML_DECLARE_SCALAR_TRAITS (swift::DeclName , QuotingType::Single)
185
+ LLVM_YAML_DECLARE_SCALAR_TRAITS (swift::AccessNoteDeclName , QuotingType::Single);
144
186
LLVM_YAML_DECLARE_SCALAR_TRAITS (swift::ObjCSelector, QuotingType::Single);
145
187
LLVM_YAML_IS_SEQUENCE_VECTOR (swift::AccessNote)
146
188
LLVM_YAML_DECLARE_MAPPING_TRAITS(swift::AccessNotes)
@@ -173,19 +215,19 @@ namespace yaml {
173
215
using AccessNote = swift::AccessNote;
174
216
using AccessNotes = swift::AccessNotes;
175
217
using ASTContext = swift::ASTContext;
176
- using DeclName = swift::DeclName ;
218
+ using AccessNoteDeclName = swift::AccessNoteDeclName ;
177
219
using ObjCSelector = swift::ObjCSelector;
178
220
179
- void ScalarTraits<DeclName >::output( const DeclName &name, void *ctxPtr,
180
- raw_ostream &os) {
181
- name.print (os, /* skipEmptyArgumentNames= */ false );
221
+ void ScalarTraits<AccessNoteDeclName >::
222
+ output ( const AccessNoteDeclName &name, void *ctxPtr, raw_ostream &os) {
223
+ name.print (os);
182
224
}
183
225
184
- StringRef ScalarTraits<DeclName >::input(StringRef str, void *ctxPtr,
185
- DeclName &name) {
226
+ StringRef ScalarTraits<AccessNoteDeclName >::
227
+ input (StringRef str, void *ctxPtr, AccessNoteDeclName &name) {
186
228
ASTContext &ctx = *static_cast <ASTContext *>(ctxPtr);
187
- name = parseDeclName (ctx, str);
188
- return name ? " " : " invalid declaration name" ;
229
+ name = AccessNoteDeclName (ctx, str);
230
+ return name. empty () ? " invalid declaration name" : " " ;
189
231
}
190
232
191
233
void ScalarTraits<ObjCSelector>::output(const ObjCSelector &selector,
@@ -207,12 +249,9 @@ StringRef ScalarTraits<ObjCSelector>::input(StringRef str, void *ctxPtr,
207
249
208
250
void MappingTraits<AccessNote>::mapping(IO &io, AccessNote ¬e) {
209
251
io.mapRequired (" Name" , note.name );
210
-
211
252
io.mapOptional (" ObjC" , note.ObjC );
212
253
io.mapOptional (" Dynamic" , note.Dynamic );
213
254
io.mapOptional (" ObjCName" , note.ObjCName );
214
-
215
- io.mapOptional (" Members" , note.members );
216
255
}
217
256
218
257
StringRef MappingTraits<AccessNote>::validate(IO &io, AccessNote ¬e) {
0 commit comments