@@ -191,11 +191,17 @@ convertToErrorAndJoin(const llvm::SMDiagnostic &diag, void *Context) {
191
191
errors = llvm::joinErrors (std::move (errors), std::move (newError));
192
192
}
193
193
194
+ struct AccessNoteYAMLContext {
195
+ ASTContext &ctx;
196
+ std::set<std::string> unknownKeys;
197
+ };
198
+
194
199
llvm::Expected<AccessNotes>
195
200
AccessNotes::load (ASTContext &ctx, llvm::MemoryBuffer *buffer) {
196
201
llvm::Error errors = llvm::Error::success ();
202
+ AccessNoteYAMLContext yamlCtx = { ctx, {} };
197
203
198
- llvm::yaml::Input yamlIn (buffer->getBuffer (), (void *)&ctx ,
204
+ llvm::yaml::Input yamlIn (buffer->getBuffer (), (void *)&yamlCtx ,
199
205
convertToErrorAndJoin, &errors);
200
206
201
207
AccessNotes notes;
@@ -204,6 +210,8 @@ AccessNotes::load(ASTContext &ctx, llvm::MemoryBuffer *buffer) {
204
210
if (errors)
205
211
return llvm::Expected<AccessNotes>(std::move (errors));
206
212
213
+ notes.unknownKeys = std::move (yamlCtx.unknownKeys );
214
+
207
215
return notes;
208
216
}
209
217
}
@@ -214,7 +222,7 @@ namespace yaml {
214
222
215
223
using AccessNote = swift::AccessNote;
216
224
using AccessNotes = swift::AccessNotes;
217
- using ASTContext = swift::ASTContext ;
225
+ using AccessNoteYAMLContext = swift::AccessNoteYAMLContext ;
218
226
using AccessNoteDeclName = swift::AccessNoteDeclName;
219
227
using ObjCSelector = swift::ObjCSelector;
220
228
@@ -225,8 +233,9 @@ output(const AccessNoteDeclName &name, void *ctxPtr, raw_ostream &os) {
225
233
226
234
StringRef ScalarTraits<AccessNoteDeclName>::
227
235
input (StringRef str, void *ctxPtr, AccessNoteDeclName &name) {
228
- ASTContext &ctx = *static_cast <ASTContext *>(ctxPtr);
229
- name = AccessNoteDeclName (ctx, str);
236
+ auto &yamlCtx = *static_cast <swift::AccessNoteYAMLContext *>(ctxPtr);
237
+
238
+ name = AccessNoteDeclName (yamlCtx.ctx , str);
230
239
return name.empty () ? " invalid declaration name" : " " ;
231
240
}
232
241
@@ -237,17 +246,46 @@ void ScalarTraits<ObjCSelector>::output(const ObjCSelector &selector,
237
246
238
247
StringRef ScalarTraits<ObjCSelector>::input(StringRef str, void *ctxPtr,
239
248
ObjCSelector &selector) {
240
- ASTContext &ctx = *static_cast <ASTContext *>(ctxPtr);
249
+ auto &yamlCtx = *static_cast <swift::AccessNoteYAMLContext *>(ctxPtr);
241
250
242
- if (auto sel = ObjCSelector::parse (ctx, str)) {
251
+ if (auto sel = ObjCSelector::parse (yamlCtx. ctx , str)) {
243
252
selector = *sel;
244
253
return " " ;
245
254
}
246
255
247
256
return " invalid selector" ;
248
257
}
249
258
259
+ // / If \p io is outputting, mark all keys in the current mapping as used.
260
+ static void diagnoseUnknownKeys (IO &io, ArrayRef<StringRef> expectedKeys) {
261
+ if (io.outputting ())
262
+ return ;
263
+
264
+ auto &yamlCtx = *static_cast <swift::AccessNoteYAMLContext *>(io.getContext ());
265
+
266
+ for (auto key : io.keys ()) {
267
+ if (is_contained (expectedKeys, key))
268
+ continue ;
269
+
270
+ // "Use" this key without actually doing anything with it to suppress the
271
+ // error llvm::yaml::Input will otherwise generate.
272
+ bool useDefault;
273
+ void *saveInfo;
274
+ if (io.preflightKey ((const char *)key.bytes_begin (), /* required=*/ false ,
275
+ /* sameAsDefault=*/ false , useDefault, saveInfo)) {
276
+ // FIXME: We should diagnose these with locations, but llvm::yaml::Input
277
+ // encapsulates all of the necessary details. Instead, we are currently
278
+ // just building a list that the frontend will display.
279
+ yamlCtx.unknownKeys .insert (key.str ());
280
+
281
+ io.postflightKey (saveInfo);
282
+ }
283
+ }
284
+ }
285
+
250
286
void MappingTraits<AccessNote>::mapping(IO &io, AccessNote ¬e) {
287
+ diagnoseUnknownKeys (io, { " Name" , " ObjC" , " Dynamic" , " ObjCName" });
288
+
251
289
io.mapRequired (" Name" , note.name );
252
290
io.mapOptional (" ObjC" , note.ObjC );
253
291
io.mapOptional (" Dynamic" , note.Dynamic );
@@ -266,6 +304,8 @@ StringRef MappingTraits<AccessNote>::validate(IO &io, AccessNote ¬e) {
266
304
}
267
305
268
306
void MappingTraits<AccessNotes>::mapping(IO &io, AccessNotes ¬es) {
307
+ diagnoseUnknownKeys (io, { " Reason" , " Notes" });
308
+
269
309
io.mapRequired (" Reason" , notes.reason );
270
310
io.mapRequired (" Notes" , notes.notes );
271
311
}
0 commit comments