15
15
// ===----------------------------------------------------------------------===//
16
16
17
17
#include " swift/AST/LocalizationFormat.h"
18
+ #include " llvm/ADT/Optional.h"
18
19
#include " llvm/ADT/SmallString.h"
19
20
#include " llvm/ADT/StringRef.h"
20
21
#include " llvm/Bitstream/BitstreamReader.h"
28
29
#include < type_traits>
29
30
30
31
namespace {
32
+
31
33
enum LocalDiagID : uint32_t {
32
34
#define DIAG (KIND, ID, Options, Text, Signature ) ID,
33
35
#include " swift/AST/DiagnosticsAll.def"
34
36
NumDiags
35
37
};
36
38
37
- struct DiagnosticNode {
38
- uint32_t id;
39
- std::string msg;
40
- };
41
39
} // namespace
42
40
43
41
namespace llvm {
@@ -55,15 +53,6 @@ template <> struct ScalarEnumerationTraits<LocalDiagID> {
55
53
}
56
54
};
57
55
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
-
67
56
} // namespace yaml
68
57
} // namespace llvm
69
58
@@ -121,6 +110,7 @@ YAMLLocalizationProducer::YAMLLocalizationProducer(llvm::StringRef filePath) {
121
110
llvm::MemoryBuffer *document = FileBufOrErr->get ();
122
111
diag::LocalizationInput yin (document->getBuffer ());
123
112
yin >> diagnostics;
113
+ unknownIDs = std::move (yin.unknownIDs );
124
114
}
125
115
126
116
llvm::StringRef
@@ -143,31 +133,45 @@ void YAMLLocalizationProducer::forEachAvailable(
143
133
}
144
134
}
145
135
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
+
146
144
template <typename T, typename Context>
147
145
typename 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) {
149
147
unsigned count = io.beginSequence ();
150
- if (count)
148
+ if (count) {
151
149
Seq.resize (LocalDiagID::NumDiags);
150
+ }
151
+
152
152
for (unsigned i = 0 ; i < count; ++i) {
153
153
void *SaveInfo;
154
154
if (io.preflightElement (i, SaveInfo)) {
155
- DiagnosticNode current;
156
- yamlize (io, current, true , Ctx);
157
- io.postflightElement (SaveInfo);
155
+ io.beginMapping ();
158
156
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)) {
164
161
// YAML file isn't guaranteed to have diagnostics in order of their
165
162
// declaration in `.def` files, to accommodate that we need to leave
166
163
// 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);
170
172
}
173
+ io.endMapping ();
174
+ io.postflightElement (SaveInfo);
171
175
}
172
176
}
173
177
io.endSequence ();
@@ -181,7 +185,7 @@ operator>>(LocalizationInput &yin, T &diagnostics) {
181
185
if (yin.setCurrentDocument ()) {
182
186
// If YAML file's format doesn't match the current format in
183
187
// DiagnosticMessageFormat, will throw an error.
184
- readYAML (yin, diagnostics, true , Ctx);
188
+ readYAML (yin, diagnostics, yin. unknownIDs , true , Ctx);
185
189
}
186
190
return yin;
187
191
}
0 commit comments