1515// ===----------------------------------------------------------------------===//
1616
1717#include " swift/AST/LocalizationFormat.h"
18+ #include " llvm/ADT/Optional.h"
1819#include " llvm/ADT/SmallString.h"
1920#include " llvm/ADT/StringRef.h"
2021#include " llvm/Bitstream/BitstreamReader.h"
2829#include < type_traits>
2930
3031namespace {
32+
3133enum LocalDiagID : uint32_t {
3234#define DIAG (KIND, ID, Options, Text, Signature ) ID,
3335#include " swift/AST/DiagnosticsAll.def"
3436 NumDiags
3537};
3638
37- struct DiagnosticNode {
38- uint32_t id;
39- std::string msg;
40- };
4139} // namespace
4240
4341namespace llvm {
@@ -55,15 +53,6 @@ template <> struct ScalarEnumerationTraits<LocalDiagID> {
5553 }
5654};
5755
58- template <> struct MappingTraits <DiagnosticNode> {
59- static void mapping (IO &io, DiagnosticNode &node) {
60- LocalDiagID diagID;
61- io.mapRequired (" id" , diagID);
62- io.mapRequired (" msg" , node.msg );
63- node.id = static_cast <uint32_t >(diagID);
64- }
65- };
66-
6756} // namespace yaml
6857} // namespace llvm
6958
@@ -121,6 +110,7 @@ YAMLLocalizationProducer::YAMLLocalizationProducer(llvm::StringRef filePath) {
121110 llvm::MemoryBuffer *document = FileBufOrErr->get ();
122111 diag::LocalizationInput yin (document->getBuffer ());
123112 yin >> diagnostics;
113+ unknownIDs = std::move (yin.unknownIDs );
124114}
125115
126116llvm::StringRef
@@ -143,31 +133,45 @@ void YAMLLocalizationProducer::forEachAvailable(
143133 }
144134}
145135
136+ llvm::Optional<uint32_t > LocalizationInput::readID (llvm::yaml::IO &io) {
137+ LocalDiagID diagID;
138+ io.mapRequired (" id" , diagID);
139+ if (diagID == LocalDiagID::NumDiags)
140+ return llvm::None;
141+ return static_cast <uint32_t >(diagID);
142+ }
143+
146144template <typename T, typename Context>
147145typename std::enable_if<llvm::yaml::has_SequenceTraits<T>::value, void >::type
148- readYAML (llvm::yaml::IO &io, T &Seq, bool , Context &Ctx) {
146+ readYAML (llvm::yaml::IO &io, T &Seq, T &unknownIDs, bool , Context &Ctx) {
149147 unsigned count = io.beginSequence ();
150- if (count)
148+ if (count) {
151149 Seq.resize (LocalDiagID::NumDiags);
150+ }
151+
152152 for (unsigned i = 0 ; i < count; ++i) {
153153 void *SaveInfo;
154154 if (io.preflightElement (i, SaveInfo)) {
155- DiagnosticNode current;
156- yamlize (io, current, true , Ctx);
157- io.postflightElement (SaveInfo);
155+ io.beginMapping ();
158156
159- // A diagnostic ID might be present in YAML and not in `.def` file,
160- // if that's the case ScalarEnumerationTraits will assign the diagnostic ID
161- // to `LocalDiagID::NumDiags`. Since the diagnostic ID isn't available
162- // in `.def` it shouldn't be stored in the diagnostics array.
163- if (current.id != LocalDiagID::NumDiags) {
157+ // If the current diagnostic ID is available in YAML and in `.def`, add it
158+ // to the diagnostics array. Otherwise, re-parse the current diagnnostic
159+ // id as a string and store it in `unknownIDs` array.
160+ if (auto id = LocalizationInput::readID (io)) {
164161 // YAML file isn't guaranteed to have diagnostics in order of their
165162 // declaration in `.def` files, to accommodate that we need to leave
166163 // holes in diagnostic array for diagnostics which haven't yet been
167- // localized and for the ones that have `DiagnosticNode::id`
168- // indicates their position.
169- Seq[static_cast <unsigned >(current.id )] = std::move (current.msg );
164+ // localized and for the ones that have `id` indicates their position.
165+ io.mapRequired (" msg" , Seq[*id]);
166+ } else {
167+ std::string unknownID, message;
168+ // Read "raw" id since it doesn't exist in `.def` file.
169+ io.mapRequired (" id" , unknownID);
170+ io.mapRequired (" msg" , message);
171+ unknownIDs.push_back (unknownID);
170172 }
173+ io.endMapping ();
174+ io.postflightElement (SaveInfo);
171175 }
172176 }
173177 io.endSequence ();
@@ -181,7 +185,7 @@ operator>>(LocalizationInput &yin, T &diagnostics) {
181185 if (yin.setCurrentDocument ()) {
182186 // If YAML file's format doesn't match the current format in
183187 // DiagnosticMessageFormat, will throw an error.
184- readYAML (yin, diagnostics, true , Ctx);
188+ readYAML (yin, diagnostics, yin. unknownIDs , true , Ctx);
185189 }
186190 return yin;
187191}
0 commit comments