Skip to content

Commit 9642cb6

Browse files
authored
Merge pull request #33337 from HassanElDesouky/localization-report-deleted-IDs
[Localization] Make the serialization tool print the removed diagnostics
2 parents 0d25abc + a3b8014 commit 9642cb6

File tree

5 files changed

+73
-30
lines changed

5 files changed

+73
-30
lines changed

include/swift/AST/LocalizationFormat.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define SWIFT_LOCALIZATIONFORMAT_H
1919

2020
#include "llvm/ADT/Hashing.h"
21+
#include "llvm/ADT/Optional.h"
2122
#include "llvm/ADT/STLExtras.h"
2223
#include "llvm/ADT/StringRef.h"
2324
#include "llvm/Bitstream/BitstreamReader.h"
@@ -38,6 +39,7 @@ namespace swift {
3839
enum class DiagID : uint32_t;
3940

4041
namespace diag {
42+
4143
using namespace llvm::support;
4244

4345
class LocalizationWriterInfo {
@@ -152,6 +154,8 @@ class YAMLLocalizationProducer final : public LocalizationProducer {
152154
std::vector<std::string> diagnostics;
153155

154156
public:
157+
/// The diagnostics IDs that are no longer available in `.def`
158+
std::vector<std::string> unknownIDs;
155159
explicit YAMLLocalizationProducer(llvm::StringRef filePath);
156160
llvm::StringRef getMessageOr(swift::DiagID id,
157161
llvm::StringRef defaultMessage) const override;
@@ -185,12 +189,23 @@ class LocalizationInput : public llvm::yaml::Input {
185189
template <typename T, typename Context>
186190
friend typename std::enable_if<llvm::yaml::has_SequenceTraits<T>::value,
187191
void>::type
188-
readYAML(llvm::yaml::IO &io, T &Seq, bool, Context &Ctx);
192+
readYAML(llvm::yaml::IO &io, T &Seq, T &unknownIDs, bool, Context &Ctx);
189193

190194
template <typename T>
191195
friend typename std::enable_if<llvm::yaml::has_SequenceTraits<T>::value,
192196
LocalizationInput &>::type
193197
operator>>(LocalizationInput &yin, T &diagnostics);
198+
199+
public:
200+
/// A vector that keeps track of the diagnostics IDs that are available in
201+
/// YAML and not available in `.def` files.
202+
std::vector<std::string> unknownIDs;
203+
204+
/// A diagnostic ID might be present in YAML and not in `.def` file, if that's
205+
/// the case the `id` won't have a `DiagID` value.
206+
/// If the `id` is available in `.def` file this method will return the `id`'s
207+
/// value, otherwise this method won't return a value.
208+
static llvm::Optional<uint32_t> readID(llvm::yaml::IO &io);
194209
};
195210

196211
} // namespace diag

lib/AST/LocalizationFormat.cpp

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
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"
@@ -28,16 +29,13 @@
2829
#include <type_traits>
2930

3031
namespace {
32+
3133
enum 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

4341
namespace 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

126116
llvm::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+
146144
template <typename T, typename Context>
147145
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) {
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
}

test/diagnostics/Localization/Inputs/en.yaml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,24 @@
2222

2323
- id: "lex_unterminated_string"
2424
msg: "unterminated string literal"
25-
25+
26+
- id: "not_available_in_def_2"
27+
msg: "Shouldn't be produced"
28+
2629
- id: "var_init_self_referential"
2730
msg: "variable used within its own initial value"
2831

2932
- id: "cannot_find_in_scope"
3033
msg: "cannot %select{find|find operator}1 %0 in scope"
3134

35+
- id: "not_available_in_def_3"
36+
msg: "Shouldn't be produced"
37+
3238
- id: "warning_invalid_locale_code"
3339
msg: "unsupported locale code; supported locale codes are '%0'"
40+
41+
- id: "not_available_in_def_4"
42+
msg: "Shouldn't be produced"
43+
44+
- id: "not_available_in_def_5"
45+
msg: "Shouldn't be produced"

test/diagnostics/Localization/fr_localization.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// RUN: %empty-directory(%t)
22
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.yaml --output-directory=%t/
3-
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/
3+
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/ 2>&1 | %FileCheck %s
44
// RUN: %target-typecheck-verify-swift -localization-path %t -locale fr
55

6+
// CHECK: These diagnostic IDs are no longer availiable: 'not_available_in_def, not_available_in_def_2, not_available_in_def_3, not_available_in_def_4, not_available_in_def_5'
67
_ = "HI!
78
// expected-error@-1{{chaîne non terminée littérale}}
89
var self1 = self1 // expected-error {{variable utilisée dans sa propre valeur initiale}}

tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "swift/AST/LocalizationFormat.h"
1818
#include "swift/Basic/LLVMInitialize.h"
19+
#include "swift/Basic/STLExtras.h"
1920
#include "llvm/ADT/SmallString.h"
2021
#include "llvm/ADT/StringExtras.h"
2122
#include "llvm/ADT/StringRef.h"
@@ -82,5 +83,15 @@ int main(int argc, char *argv[]) {
8283
return EXIT_FAILURE;
8384
}
8485

86+
// Print out the diagnostics IDs that are available in YAML but not available
87+
// in `.def`
88+
if (!yaml.unknownIDs.empty()) {
89+
llvm::errs() << "These diagnostic IDs are no longer availiable: '";
90+
llvm::interleave(
91+
yaml.unknownIDs, [&](std::string id) { llvm::errs() << id; },
92+
[&] { llvm::errs() << ", "; });
93+
llvm::errs() << "'\n";
94+
}
95+
8596
return EXIT_SUCCESS;
8697
}

0 commit comments

Comments
 (0)