Skip to content

Commit ef7551d

Browse files
[Localization] Add an allocator to to retain diagnostic strings
1 parent 651655e commit ef7551d

File tree

5 files changed

+63
-27
lines changed

5 files changed

+63
-27
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/Support/Allocator.h"
3030
#include "llvm/Support/FileSystem.h"
3131
#include "llvm/Support/Path.h"
32+
#include "llvm/Support/StringSaver.h"
3233
#include "llvm/Support/VersionTuple.h"
3334

3435
namespace swift {
@@ -721,6 +722,11 @@ namespace swift {
721722
/// diagnostic message.
722723
std::unique_ptr<diag::LocalizationProducer> localization;
723724

725+
/// This allocator will retain localized diagnostic strings for the duration
726+
/// of compiler invocation.
727+
llvm::BumpPtrAllocator localizationAllocator;
728+
llvm::Optional<llvm::StringSaver> localizationSaver;
729+
724730
/// The number of open diagnostic transactions. Diagnostics are only
725731
/// emitted once all transactions have closed.
726732
unsigned TransactionCount = 0;
@@ -744,7 +750,8 @@ namespace swift {
744750
public:
745751
explicit DiagnosticEngine(SourceManager &SourceMgr)
746752
: SourceMgr(SourceMgr), ActiveDiagnostic(),
747-
TransactionStrings(TransactionAllocator) {}
753+
TransactionStrings(TransactionAllocator),
754+
localizationSaver(localizationAllocator) {}
748755

749756
/// hadAnyError - return true if any *error* diagnostics have been emitted.
750757
bool hadAnyError() const { return state.hadAnyError(); }
@@ -804,15 +811,16 @@ namespace swift {
804811
if (llvm::sys::fs::exists(filePath)) {
805812
if (auto file = llvm::MemoryBuffer::getFile(filePath)) {
806813
localization = std::make_unique<diag::SerializedLocalizationProducer>(
807-
std::move(file.get()), getPrintDiagnosticNames());
814+
std::move(file.get()), localizationSaver,
815+
getPrintDiagnosticNames());
808816
}
809817
} else {
810818
llvm::sys::path::replace_extension(filePath, ".yaml");
811819
// In case of missing localization files, we should fallback to messages
812820
// from `.def` files.
813821
if (llvm::sys::fs::exists(filePath)) {
814822
localization = std::make_unique<diag::YAMLLocalizationProducer>(
815-
filePath.str(), getPrintDiagnosticNames());
823+
filePath.str(), localizationSaver, getPrintDiagnosticNames());
816824
}
817825
}
818826
}

include/swift/Localization/LocalizationFormat.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/Support/EndianStream.h"
2727
#include "llvm/Support/MemoryBuffer.h"
2828
#include "llvm/Support/OnDiskHashTable.h"
29+
#include "llvm/Support/StringSaver.h"
2930
#include "llvm/Support/YAMLParser.h"
3031
#include "llvm/Support/YAMLTraits.h"
3132
#include "llvm/Support/raw_ostream.h"
@@ -154,12 +155,15 @@ class SerializedLocalizationWriter {
154155
};
155156

156157
class LocalizationProducer {
158+
llvm::Optional<llvm::StringSaver> localizationSaver;
157159
bool printDiagnosticName;
158-
std::string localizedDebugDiagnosticMessage;
159160

160161
public:
161-
LocalizationProducer(bool printDiagnosticName = false)
162-
: printDiagnosticName(printDiagnosticName) {}
162+
LocalizationProducer(llvm::Optional<llvm::StringSaver> localizationSaver =
163+
llvm::Optional<llvm::StringSaver>(),
164+
bool printDiagnosticName = false)
165+
: localizationSaver(localizationSaver),
166+
printDiagnosticName(printDiagnosticName) {}
163167

164168
/// If the message isn't available/localized in current context
165169
/// return the fallback default message.
@@ -180,8 +184,11 @@ class YAMLLocalizationProducer final : public LocalizationProducer {
180184
public:
181185
/// The diagnostics IDs that are no longer available in `.def`
182186
std::vector<std::string> unknownIDs;
183-
explicit YAMLLocalizationProducer(llvm::StringRef filePath,
184-
bool printDiagnosticName = false);
187+
explicit YAMLLocalizationProducer(
188+
llvm::StringRef filePath,
189+
llvm::Optional<llvm::StringSaver> localizationSaver =
190+
llvm::Optional<llvm::StringSaver>(),
191+
bool printDiagnosticName = false);
185192

186193
/// Iterate over all of the available (non-empty) translations
187194
/// maintained by this producer, callback gets each translation
@@ -203,6 +210,8 @@ class SerializedLocalizationProducer final : public LocalizationProducer {
203210
public:
204211
explicit SerializedLocalizationProducer(
205212
std::unique_ptr<llvm::MemoryBuffer> buffer,
213+
llvm::Optional<llvm::StringSaver> localizationSaver =
214+
llvm::Optional<llvm::StringSaver>(),
206215
bool printDiagnosticName = false);
207216

208217
protected:

lib/Localization/LocalizationFormat.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,20 @@ LocalizationProducer::getMessageOr(swift::DiagID id,
9898
if (localizedMessage.empty())
9999
return defaultMessage;
100100
llvm::StringRef diagnosticName(diagnosticNameStrings[(unsigned)id]);
101-
localizedDebugDiagnosticMessage =
102-
localizedMessage.str() + diagnosticName.str();
103-
return printDiagnosticName ? localizedDebugDiagnosticMessage
104-
: localizedMessage;
101+
if (localizationSaver && printDiagnosticName) {
102+
auto localizedDebugDiagnosticMessage =
103+
localizationSaver->save(localizedMessage.str() + diagnosticName.str());
104+
return localizedDebugDiagnosticMessage;
105+
}
106+
return localizedMessage;
105107
}
106108

107109
SerializedLocalizationProducer::SerializedLocalizationProducer(
108-
std::unique_ptr<llvm::MemoryBuffer> buffer, bool printDiagnosticName)
109-
: LocalizationProducer(printDiagnosticName), Buffer(std::move(buffer)) {
110+
std::unique_ptr<llvm::MemoryBuffer> buffer,
111+
llvm::Optional<llvm::StringSaver> localizationSaver,
112+
bool printDiagnosticName)
113+
: LocalizationProducer(localizationSaver, printDiagnosticName),
114+
Buffer(std::move(buffer)) {
110115
auto base =
111116
reinterpret_cast<const unsigned char *>(Buffer.get()->getBufferStart());
112117
auto tableOffset = endian::read<offset_type>(base, little);
@@ -122,9 +127,11 @@ SerializedLocalizationProducer::getMessage(swift::DiagID id) const {
122127
return {(const char *)value.getDataPtr(), value.getDataLen()};
123128
}
124129

125-
YAMLLocalizationProducer::YAMLLocalizationProducer(llvm::StringRef filePath,
126-
bool printDiagnosticName)
127-
: LocalizationProducer(printDiagnosticName) {
130+
YAMLLocalizationProducer::YAMLLocalizationProducer(
131+
llvm::StringRef filePath,
132+
llvm::Optional<llvm::StringSaver> localizationSaver,
133+
bool printDiagnosticName)
134+
: LocalizationProducer(localizationSaver, printDiagnosticName) {
128135
auto FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(filePath);
129136
llvm::MemoryBuffer *document = FileBufOrErr->get();
130137
diag::LocalizationInput yin(document->getBuffer());
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
// RUN: %target-typecheck-verify-swift -localization-path %S/Inputs -locale en
1+
// RUN: not %target-swift-frontend -typecheck %s 2>&1 -localization-path %S/Inputs -locale en | %FileCheck %s --check-prefix=CHECK_NONAMES
2+
// RUN: not %target-swift-frontend -debug-diagnostic-names -localization-path %S/Inputs -locale en -typecheck %s 2>&1 | %FileCheck %s --check-prefix=CHECK_NAMES
23

34
_ = "HI!
4-
// expected-error@-1{{unterminated string literal}}
5+
// CHECK_NONAMES: error: unterminated string literal{{$}}
6+
// CHECK_NAMES: error: unterminated string literal [lex_unterminated_string]{{$}}
7+
58
var self1 = self1
6-
// expected-note@-1 2{{through reference here}}
7-
// expected-error@-2 {{circular reference}}
9+
// CHECK_NONAMES: error: circular reference{{$}}
10+
// CHECK_NONAMES: note: through reference here{{$}}
11+
// CHECK_NAMES: error: circular reference [circular_reference]{{$}}
12+
// CHECK_NAMES: note: through reference here [circular_reference_through]{{$}}
813
914
struct Broken {
10-
var b : Bool = True // expected-error{{cannot find 'True' in scope}}
15+
var b : Bool = True
1116
}
17+
// CHECK_NONAMES: error: cannot find 'True' in scope{{$}}
1218
// CHECK_NAMES: error: cannot find 'True' in scope [cannot_find_in_scope]{{$}}
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
// RUN: %empty-directory(%t)
22
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.yaml --output-directory=%t/
33
// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/ 2>&1 | %FileCheck %s
4-
// RUN: %target-typecheck-verify-swift -localization-path %t -locale fr
4+
// RUN: not %target-swift-frontend -typecheck %s 2>&1 -localization-path %S/Inputs -locale fr | %FileCheck %s --check-prefix=CHECK_NONAMES
5+
// RUN: not %target-swift-frontend -debug-diagnostic-names -localization-path %S/Inputs -locale fr -typecheck %s 2>&1 | %FileCheck %s --check-prefix=CHECK_NAMES
56

67
// 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'
78
_ = "HI!
8-
// expected-error@-1{{chaîne non terminée littérale}}
9+
// CHECK_NONAMES: error: chaîne non terminée littérale{{$}}
10+
// CHECK_NAMES: error: chaîne non terminée littérale [lex_unterminated_string]{{$}}
911
1012
// FIXME: This used to produce a localized diagnostic.
1113
12-
var self1 = self1 // expected-note 2{{through reference here}}
13-
// expected-error@-1 {{circular reference}}
14+
var self1 = self1
15+
// CHECK_NONAMES: error: circular reference{{$}}
16+
// CHECK_NONAMES: note: through reference here{{$}}
17+
// CHECK_NAMES: error: circular reference [circular_reference]{{$}}
18+
// CHECK_NAMES: note: through reference here [circular_reference_through]{{$}}
1419
1520
struct Broken {
16-
var b : Bool = True // expected-error{{impossible de trouver 'True' portée}}
21+
var b : Bool = True
1722
}
23+
// CHECK_NONAMES: error: impossible de trouver 'True' portée{{$}}
1824
// CHECK_NAMES: error: impossible de trouver 'True' portée [cannot_find_in_scope]{{$}}

0 commit comments

Comments
 (0)