Skip to content

Commit b272a05

Browse files
authored
Merge pull request #76363 from DmT021/wp/print-diagnostic-groups
[Diagnostics] Add -print-diagnostic-groups flag
2 parents 6cf878c + a8b71ea commit b272a05

31 files changed

+376
-315
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/DeclNameLoc.h"
2323
#include "swift/AST/DiagnosticConsumer.h"
2424
#include "swift/AST/TypeLoc.h"
25+
#include "swift/Basic/PrintDiagnosticNamesMode.h"
2526
#include "swift/Basic/Statistic.h"
2627
#include "swift/Basic/Version.h"
2728
#include "swift/Basic/WarningAsErrorRule.h"
@@ -1065,6 +1066,13 @@ namespace swift {
10651066
/// diagnostic message.
10661067
std::unique_ptr<diag::LocalizationProducer> localization;
10671068

1069+
/// This allocator will retain diagnostic strings containing the
1070+
/// diagnostic's message and identifier as `message [id]` for the duration
1071+
/// of compiler invocation. This will be used when the frontend flags
1072+
/// `-debug-diagnostic-names` or `-print-diagnostic-groups` are used.
1073+
llvm::BumpPtrAllocator DiagnosticStringsAllocator;
1074+
llvm::StringSaver DiagnosticStringsSaver;
1075+
10681076
/// The number of open diagnostic transactions. Diagnostics are only
10691077
/// emitted once all transactions have closed.
10701078
unsigned TransactionCount = 0;
@@ -1074,9 +1082,11 @@ namespace swift {
10741082
/// input being compiled.
10751083
/// May be invalid.
10761084
SourceLoc bufferIndirectlyCausingDiagnostic;
1077-
1078-
/// Print diagnostic names after their messages
1079-
bool printDiagnosticNames = false;
1085+
1086+
/// When printing diagnostics, include either the diagnostic name
1087+
/// (diag::whatever) at the end or the associated diagnostic group.
1088+
PrintDiagnosticNamesMode printDiagnosticNamesMode =
1089+
PrintDiagnosticNamesMode::None;
10801090

10811091
/// Path to diagnostic documentation directory.
10821092
std::string diagnosticDocumentationPath = "";
@@ -1102,7 +1112,8 @@ namespace swift {
11021112
public:
11031113
explicit DiagnosticEngine(SourceManager &SourceMgr)
11041114
: SourceMgr(SourceMgr), ActiveDiagnostic(),
1105-
TransactionStrings(TransactionAllocator) {}
1115+
TransactionStrings(TransactionAllocator),
1116+
DiagnosticStringsSaver(DiagnosticStringsAllocator) {}
11061117

11071118
/// hadAnyError - return true if any *error* diagnostics have been emitted.
11081119
bool hadAnyError() const { return state.hadAnyError(); }
@@ -1144,11 +1155,11 @@ namespace swift {
11441155
void setWarningsAsErrorsRules(const std::vector<WarningAsErrorRule> &rules);
11451156

11461157
/// Whether to print diagnostic names after their messages
1147-
void setPrintDiagnosticNames(bool val) {
1148-
printDiagnosticNames = val;
1158+
void setPrintDiagnosticNamesMode(PrintDiagnosticNamesMode val) {
1159+
printDiagnosticNamesMode = val;
11491160
}
1150-
bool getPrintDiagnosticNames() const {
1151-
return printDiagnosticNames;
1161+
PrintDiagnosticNamesMode getPrintDiagnosticNamesMode() const {
1162+
return printDiagnosticNamesMode;
11521163
}
11531164

11541165
void setDiagnosticDocumentationPath(std::string path) {
@@ -1169,8 +1180,7 @@ namespace swift {
11691180
void setLocalization(StringRef locale, StringRef path) {
11701181
assert(!locale.empty());
11711182
assert(!path.empty());
1172-
localization = diag::LocalizationProducer::producerFor(
1173-
locale, path, getPrintDiagnosticNames());
1183+
localization = diag::LocalizationProducer::producerFor(locale, path);
11741184
}
11751185

11761186
void ignoreDiagnostic(DiagID id) {
@@ -1426,8 +1436,9 @@ namespace swift {
14261436
public:
14271437
DiagnosticKind declaredDiagnosticKindFor(const DiagID id);
14281438

1429-
llvm::StringRef diagnosticStringFor(const DiagID id,
1430-
bool printDiagnosticNames);
1439+
llvm::StringRef
1440+
diagnosticStringFor(const DiagID id,
1441+
PrintDiagnosticNamesMode printDiagnosticNamesMode);
14311442

14321443
static llvm::StringRef diagnosticIDStringFor(const DiagID id);
14331444

include/swift/Basic/DiagnosticOptions.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef SWIFT_BASIC_DIAGNOSTICOPTIONS_H
1414
#define SWIFT_BASIC_DIAGNOSTICOPTIONS_H
1515

16+
#include "swift/Basic/PrintDiagnosticNamesMode.h"
1617
#include "swift/Basic/WarningAsErrorRule.h"
1718
#include "llvm/ADT/Hashing.h"
1819
#include <vector>
@@ -63,9 +64,10 @@ class DiagnosticOptions {
6364
/// Rules for escalating warnings to errors
6465
std::vector<WarningAsErrorRule> WarningsAsErrorsRules;
6566

66-
/// When printing diagnostics, include the diagnostic name (diag::whatever) at
67-
/// the end.
68-
bool PrintDiagnosticNames = false;
67+
/// When printing diagnostics, include either the diagnostic name
68+
/// (diag::whatever) at the end or the associated diagnostic group.
69+
PrintDiagnosticNamesMode PrintDiagnosticNames =
70+
PrintDiagnosticNamesMode::None;
6971

7072
/// If set to true, include educational notes in printed output if available.
7173
/// Educational notes are documentation which supplement diagnostics.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===--- PrintDiagnosticNamesMode.h -----------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_BASIC_PRINTDIAGNOSTICNAMESMODE_H
14+
#define SWIFT_BASIC_PRINTDIAGNOSTICNAMESMODE_H
15+
16+
namespace swift {
17+
18+
/// What diagnostic name will be printed alongside the diagnostic message.
19+
enum class PrintDiagnosticNamesMode {
20+
/// No diagnostic name will be printed.
21+
None,
22+
23+
/// The identifier of a diagnostic (DiagID) will be used. Corresponds to the
24+
/// `-debug-diagnostic-names` option in the frontend.
25+
Identifier,
26+
27+
/// The associated group name (DiagGroupID) will be used. Corresponds to the
28+
/// `-print-diagnostic-groups` option in the frontend.
29+
Group
30+
};
31+
32+
} // end namespace swift
33+
34+
#endif // SWIFT_BASIC_PRINTDIAGNOSTICNAMESMODE_H

include/swift/Localization/LocalizationFormat.h

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -157,20 +157,9 @@ class SerializedLocalizationWriter {
157157
};
158158

159159
class LocalizationProducer {
160-
/// This allocator will retain localized diagnostic strings containing the
161-
/// diagnostic's message and identifier as `message [id]` for the duration of
162-
/// compiler invocation. This will be used when the frontend flag
163-
/// `-debug-diagnostic-names` is used.
164-
llvm::BumpPtrAllocator localizationAllocator;
165-
llvm::StringSaver localizationSaver;
166-
bool printDiagnosticNames;
167160
LocalizationProducerState state = NotInitialized;
168161

169162
public:
170-
LocalizationProducer(bool printDiagnosticNames = false)
171-
: localizationSaver(localizationAllocator),
172-
printDiagnosticNames(printDiagnosticNames) {}
173-
174163
/// If the message isn't available/localized in current context
175164
/// return the fallback default message.
176165
virtual llvm::StringRef getMessageOr(swift::DiagID id,
@@ -181,8 +170,7 @@ class LocalizationProducer {
181170
/// `StringsLocalizationProducer` if the `.strings` file is available. If both
182171
/// files aren't available returns a `nullptr`.
183172
static std::unique_ptr<LocalizationProducer>
184-
producerFor(llvm::StringRef locale, llvm::StringRef path,
185-
bool printDiagnosticNames);
173+
producerFor(llvm::StringRef locale, llvm::StringRef path);
186174

187175
virtual ~LocalizationProducer() {}
188176

@@ -206,9 +194,8 @@ class StringsLocalizationProducer final : public LocalizationProducer {
206194
std::vector<std::string> diagnostics;
207195

208196
public:
209-
explicit StringsLocalizationProducer(llvm::StringRef filePath,
210-
bool printDiagnosticNames = false)
211-
: LocalizationProducer(printDiagnosticNames), filePath(filePath) {}
197+
explicit StringsLocalizationProducer(llvm::StringRef filePath)
198+
: LocalizationProducer(), filePath(filePath) {}
212199

213200
/// Iterate over all of the available (non-empty) translations
214201
/// maintained by this producer, callback gets each translation
@@ -234,8 +221,7 @@ class SerializedLocalizationProducer final : public LocalizationProducer {
234221

235222
public:
236223
explicit SerializedLocalizationProducer(
237-
std::unique_ptr<llvm::MemoryBuffer> buffer,
238-
bool printDiagnosticNames = false);
224+
std::unique_ptr<llvm::MemoryBuffer> buffer);
239225

240226
protected:
241227
bool initializeImpl() override;

include/swift/Option/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,9 @@ def no_color_diagnostics : Flag<["-"], "no-color-diagnostics">,
469469
def debug_diagnostic_names : Flag<["-"], "debug-diagnostic-names">,
470470
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, HelpHidden]>,
471471
HelpText<"Include diagnostic names when printing">;
472+
def print_diagnostic_groups : Flag<["-"], "print-diagnostic-groups">,
473+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, HelpHidden]>,
474+
HelpText<"Include diagnostic groups in printed diagnostic output, if available">;
472475
def print_educational_notes : Flag<["-"], "print-educational-notes">,
473476
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
474477
HelpText<"Include educational notes in printed diagnostic output, if available">;

lib/AST/DiagnosticEngine.cpp

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,6 @@ static constexpr const char * const diagnosticStrings[] = {
133133
"<not a diagnostic>",
134134
};
135135

136-
static constexpr const char *const debugDiagnosticStrings[] = {
137-
#define DIAG(KIND, ID, Group, Options, Text, Signature) Text " [" #ID "]",
138-
#include "swift/AST/DiagnosticsAll.def"
139-
"<not a diagnostic>",
140-
};
141-
142136
static constexpr const char *const diagnosticIDStrings[] = {
143137
#define DIAG(KIND, ID, Group, Options, Text, Signature) #ID,
144138
#include "swift/AST/DiagnosticsAll.def"
@@ -1522,7 +1516,7 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
15221516

15231517
return DiagnosticInfo(
15241518
diagnostic.getID(), loc, toDiagnosticKind(behavior),
1525-
diagnosticStringFor(diagnostic.getID(), getPrintDiagnosticNames()),
1519+
diagnosticStringFor(diagnostic.getID(), getPrintDiagnosticNamesMode()),
15261520
diagnostic.getArgs(), Category, getDefaultDiagnosticLoc(),
15271521
/*child note info*/ {}, diagnostic.getRanges(), fixIts,
15281522
diagnostic.isChildNote());
@@ -1687,18 +1681,38 @@ DiagnosticKind DiagnosticEngine::declaredDiagnosticKindFor(const DiagID id) {
16871681
return storedDiagnosticInfos[(unsigned)id].kind;
16881682
}
16891683

1690-
llvm::StringRef
1691-
DiagnosticEngine::diagnosticStringFor(const DiagID id,
1692-
bool printDiagnosticNames) {
1693-
auto defaultMessage = printDiagnosticNames
1694-
? debugDiagnosticStrings[(unsigned)id]
1695-
: diagnosticStrings[(unsigned)id];
1696-
1697-
if (auto producer = localization.get()) {
1698-
auto localizedMessage = producer->getMessageOr(id, defaultMessage);
1699-
return localizedMessage;
1684+
llvm::StringRef DiagnosticEngine::diagnosticStringFor(
1685+
const DiagID id, PrintDiagnosticNamesMode printDiagnosticNamesMode) {
1686+
llvm::StringRef message = diagnosticStrings[(unsigned)id];
1687+
if (auto localizationProducer = localization.get()) {
1688+
message = localizationProducer->getMessageOr(id, message);
1689+
}
1690+
auto formatMessageWithName = [&](StringRef message, StringRef name) {
1691+
const int additionalCharsLength = 3; // ' ', '[', ']'
1692+
std::string messageWithName;
1693+
messageWithName.reserve(message.size() + name.size() +
1694+
additionalCharsLength);
1695+
messageWithName += message;
1696+
messageWithName += " [";
1697+
messageWithName += name;
1698+
messageWithName += "]";
1699+
return DiagnosticStringsSaver.save(messageWithName);
1700+
};
1701+
switch (printDiagnosticNamesMode) {
1702+
case PrintDiagnosticNamesMode::None:
1703+
break;
1704+
case PrintDiagnosticNamesMode::Identifier:
1705+
message = formatMessageWithName(message, diagnosticIDStringFor(id));
1706+
break;
1707+
case PrintDiagnosticNamesMode::Group:
1708+
auto groupID = storedDiagnosticInfos[(unsigned)id].groupID;
1709+
if (groupID != DiagGroupID::no_group) {
1710+
message =
1711+
formatMessageWithName(message, getDiagGroupInfoByID(groupID).name);
1712+
}
1713+
break;
17001714
}
1701-
return defaultMessage;
1715+
return message;
17021716
}
17031717

17041718
llvm::StringRef

lib/DriverTool/sil_opt_main.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -717,8 +717,10 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
717717

718718
Invocation.getLangOptions().BypassResilienceChecks =
719719
options.BypassResilienceChecks;
720-
Invocation.getDiagnosticOptions().PrintDiagnosticNames =
721-
options.DebugDiagnosticNames;
720+
if (options.DebugDiagnosticNames) {
721+
Invocation.getDiagnosticOptions().PrintDiagnosticNames =
722+
PrintDiagnosticNamesMode::Identifier;
723+
}
722724

723725
for (auto &featureName : options.UpcomingFeatures) {
724726
auto feature = getUpcomingFeature(featureName);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2349,7 +2349,11 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
23492349
}
23502350
}());
23512351
}
2352-
Opts.PrintDiagnosticNames |= Args.hasArg(OPT_debug_diagnostic_names);
2352+
if (Args.hasArg(OPT_debug_diagnostic_names)) {
2353+
Opts.PrintDiagnosticNames = PrintDiagnosticNamesMode::Identifier;
2354+
} else if (Args.hasArg(OPT_print_diagnostic_groups)) {
2355+
Opts.PrintDiagnosticNames = PrintDiagnosticNamesMode::Group;
2356+
}
23532357
Opts.PrintEducationalNotes |= Args.hasArg(OPT_print_educational_notes);
23542358
if (Arg *A = Args.getLastArg(OPT_diagnostic_documentation_path)) {
23552359
Opts.DiagnosticDocumentationPath = A->getValue();

lib/Frontend/Frontend.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -729,9 +729,8 @@ void CompilerInstance::setUpDiagnosticOptions() {
729729
}
730730
Diagnostics.setWarningsAsErrorsRules(
731731
Invocation.getDiagnosticOptions().WarningsAsErrorsRules);
732-
if (Invocation.getDiagnosticOptions().PrintDiagnosticNames) {
733-
Diagnostics.setPrintDiagnosticNames(true);
734-
}
732+
Diagnostics.setPrintDiagnosticNamesMode(
733+
Invocation.getDiagnosticOptions().PrintDiagnosticNames);
735734
Diagnostics.setDiagnosticDocumentationPath(
736735
Invocation.getDiagnosticOptions().DiagnosticDocumentationPath);
737736
Diagnostics.setLanguageVersion(

lib/IDE/CodeCompletionDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ bool CodeCompletionDiagnostics::getDiagnostics(
6767
typename swift::detail::PassArgument<ArgTypes>::type... VArgs) {
6868
DiagID id = ID.ID;
6969
std::vector<DiagnosticArgument> DiagArgs{std::move(VArgs)...};
70-
auto format = Engine.diagnosticStringFor(id, /*printDiagnosticNames=*/false);
70+
auto format = Engine.diagnosticStringFor(id, PrintDiagnosticNamesMode::None);
7171
DiagnosticEngine::formatDiagnosticText(Out, format, DiagArgs);
7272
severity = getSeverity(Engine.declaredDiagnosticKindFor(id));
7373

lib/Localization/LocalizationFormat.cpp

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,6 @@ enum LocalDiagID : uint32_t {
3939
NumDiags
4040
};
4141

42-
static constexpr const char *const diagnosticNameStrings[] = {
43-
#define DIAG(KIND, ID, Group, Options, Text, Signature) " [" #ID "]",
44-
#include "swift/AST/DiagnosticsAll.def"
45-
"<not a diagnostic>",
46-
};
47-
4842
} // namespace
4943

5044
namespace swift {
@@ -96,12 +90,6 @@ LocalizationProducer::getMessageOr(swift::DiagID id,
9690
auto localizedMessage = getMessage(id);
9791
if (localizedMessage.empty())
9892
return defaultMessage;
99-
if (printDiagnosticNames) {
100-
llvm::StringRef diagnosticName(diagnosticNameStrings[(unsigned)id]);
101-
auto localizedDebugDiagnosticMessage =
102-
localizationSaver.save(localizedMessage.str() + diagnosticName.str());
103-
return localizedDebugDiagnosticMessage;
104-
}
10593
return localizedMessage;
10694
}
10795

@@ -110,9 +98,8 @@ LocalizationProducerState LocalizationProducer::getState() const {
11098
}
11199

112100
SerializedLocalizationProducer::SerializedLocalizationProducer(
113-
std::unique_ptr<llvm::MemoryBuffer> buffer, bool printDiagnosticNames)
114-
: LocalizationProducer(printDiagnosticNames), Buffer(std::move(buffer)) {
115-
}
101+
std::unique_ptr<llvm::MemoryBuffer> buffer)
102+
: LocalizationProducer(), Buffer(std::move(buffer)) {}
116103

117104
bool SerializedLocalizationProducer::initializeImpl() {
118105
auto base =
@@ -132,8 +119,8 @@ SerializedLocalizationProducer::getMessage(swift::DiagID id) const {
132119
}
133120

134121
std::unique_ptr<LocalizationProducer>
135-
LocalizationProducer::producerFor(llvm::StringRef locale, llvm::StringRef path,
136-
bool printDiagnosticNames) {
122+
LocalizationProducer::producerFor(llvm::StringRef locale,
123+
llvm::StringRef path) {
137124
llvm::SmallString<128> filePath(path);
138125
llvm::sys::path::append(filePath, locale);
139126
llvm::sys::path::replace_extension(filePath, ".db");
@@ -143,13 +130,13 @@ LocalizationProducer::producerFor(llvm::StringRef locale, llvm::StringRef path,
143130
if (llvm::sys::fs::exists(filePath)) {
144131
if (auto file = llvm::MemoryBuffer::getFile(filePath)) {
145132
return std::make_unique<diag::SerializedLocalizationProducer>(
146-
std::move(file.get()), printDiagnosticNames);
133+
std::move(file.get()));
147134
}
148135
} else {
149136
llvm::sys::path::replace_extension(filePath, ".strings");
150137
if (llvm::sys::fs::exists(filePath)) {
151138
return std::make_unique<diag::StringsLocalizationProducer>(
152-
filePath.str(), printDiagnosticNames);
139+
filePath.str());
153140
}
154141
}
155142

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,7 @@ class ModuleWriter {
973973
// Emit a specific unavailable message when we know why a decl can't be
974974
// exposed, or a generic message otherwise.
975975
auto diagString = M.getASTContext().Diags.diagnosticStringFor(
976-
diag.getID(), /*PrintDiagnosticNames=*/false);
976+
diag.getID(), PrintDiagnosticNamesMode::None);
977977
DiagnosticEngine::formatDiagnosticText(os, diagString, diag.getArgs(),
978978
DiagnosticFormatOptions());
979979
os << "\");\n";

0 commit comments

Comments
 (0)