Skip to content

Commit 7934a16

Browse files
DmT021AnthonyLatsis
authored andcommitted
DiagnosticEngine: Add DiagGroupID to Diagnostic
This change addresses the following issue: when an error is being wrapped in a warning, the diagnostic message will use the wrapper's `DiagGroupID` as the warning's name. However, we want to retain the original error's group for use. For example, in Swift 5, `async_unavailable_decl` is wrapped in `error_in_future_swift_version`. When we print a diagnostic of this kind, we want to keep the `DiagGroupID` of `async_unavailable_decl`, not that of `error_in_future_swift_version`. To achieve this, we add `DiagGroupID` to the `Diagnostic` class. When an active diagnostic is wrapped in `DiagnosticEngine`, we retain the original `DiagGroupID`.
1 parent 38a990a commit 7934a16

File tree

5 files changed

+62
-22
lines changed

5 files changed

+62
-22
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ namespace swift {
6767
/// this enumeration type that uniquely identifies it.
6868
enum class DiagID : uint32_t;
6969

70+
enum class DiagGroupID : uint16_t;
71+
7072
/// Describes a diagnostic along with its argument types.
7173
///
7274
/// The diagnostics header introduces instances of this type for each
@@ -498,6 +500,7 @@ namespace swift {
498500

499501
private:
500502
DiagID ID;
503+
DiagGroupID GroupID;
501504
SmallVector<DiagnosticArgument, 3> Args;
502505
SmallVector<CharSourceRange, 2> Ranges;
503506
SmallVector<FixIt, 2> FixIts;
@@ -510,7 +513,10 @@ namespace swift {
510513
friend DiagnosticEngine;
511514
friend class InFlightDiagnostic;
512515

513-
Diagnostic(DiagID ID) : ID(ID) {}
516+
Diagnostic(DiagID ID, DiagGroupID GroupID) : ID(ID), GroupID(GroupID) {}
517+
518+
/// Constructs a Diagnostic with DiagGroupID infered from DiagID.
519+
Diagnostic(DiagID ID);
514520

515521
public:
516522
// All constructors are intentionally implicit.
@@ -535,6 +541,7 @@ namespace swift {
535541

536542
// Accessors.
537543
DiagID getID() const { return ID; }
544+
DiagGroupID getGroupID() const { return GroupID; }
538545
ArrayRef<DiagnosticArgument> getArgs() const { return Args; }
539546
ArrayRef<CharSourceRange> getRanges() const { return Ranges; }
540547
ArrayRef<FixIt> getFixIts() const { return FixIts; }
@@ -1434,7 +1441,8 @@ namespace swift {
14341441

14351442
/// Generate DiagnosticInfo for a Diagnostic to be passed to consumers.
14361443
std::optional<DiagnosticInfo>
1437-
diagnosticInfoForDiagnostic(const Diagnostic &diagnostic);
1444+
diagnosticInfoForDiagnostic(const Diagnostic &diagnostic,
1445+
bool includeDiagnosticName);
14381446

14391447
/// Send \c diag to all diagnostic consumers.
14401448
void emitDiagnostic(const Diagnostic &diag);
@@ -1460,9 +1468,16 @@ namespace swift {
14601468
public:
14611469
DiagnosticKind declaredDiagnosticKindFor(const DiagID id);
14621470

1463-
llvm::StringRef
1464-
diagnosticStringFor(const DiagID id,
1465-
PrintDiagnosticNamesMode printDiagnosticNamesMode);
1471+
/// Get a localized format string for a given `DiagID`. If no localization
1472+
/// available returns the default string for that `DiagID`.
1473+
llvm::StringRef diagnosticStringFor(DiagID id);
1474+
1475+
/// Get a localized format string with an optional diagnostic name appended
1476+
/// to it. The diagnostic name type is defined by
1477+
/// `PrintDiagnosticNamesMode`.
1478+
llvm::StringRef diagnosticStringWithNameFor(
1479+
DiagID id, DiagGroupID groupID,
1480+
PrintDiagnosticNamesMode printDiagnosticNamesMode);
14661481

14671482
static llvm::StringRef diagnosticIDStringFor(const DiagID id);
14681483

include/swift/AST/DiagnosticsCommon.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,14 @@ ERROR(error_no_group_info,none,
4747
NOTE(brace_stmt_suggest_do,none,
4848
"did you mean to use a 'do' statement?", ())
4949

50+
// `error_in_future_swift_version` does not have a group because warnings of this kind
51+
// inherit the group from the wrapped error.
5052
WARNING(error_in_future_swift_version,none,
5153
"%0; this is an error in the Swift %1 language mode",
5254
(DiagnosticInfo *, unsigned))
5355

56+
// `error_in_a_future_swift_version` does not have a group because warnings of this kind
57+
// inherit the group from the wrapped error.
5458
WARNING(error_in_a_future_swift_version,none,
5559
"%0; this will be an error in a future Swift language mode",
5660
(DiagnosticInfo *))

lib/AST/DiagnosticEngine.cpp

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ DiagnosticState::DiagnosticState() {
179179
warningsAsErrors.resize(LocalDiagID::NumDiags);
180180
}
181181

182+
Diagnostic::Diagnostic(DiagID ID)
183+
: Diagnostic(ID, storedDiagnosticInfos[(unsigned)ID].groupID) {}
184+
182185
static CharSourceRange toCharSourceRange(SourceManager &SM, SourceRange SR) {
183186
return CharSourceRange(SM, SR.Start, Lexer::getLocForEndOfToken(SM, SR.End));
184187
}
@@ -464,8 +467,8 @@ InFlightDiagnostic::wrapIn(const Diagnostic &wrapper) {
464467
limit(Engine->getActiveDiagnostic().BehaviorLimit,
465468
DiagnosticBehavior::Unspecified);
466469

467-
Engine->WrappedDiagnostics.push_back(
468-
*Engine->diagnosticInfoForDiagnostic(Engine->getActiveDiagnostic()));
470+
Engine->WrappedDiagnostics.push_back(*Engine->diagnosticInfoForDiagnostic(
471+
Engine->getActiveDiagnostic(), /* includeDiagnosticName= */ false));
469472

470473
Engine->state.swap(tempState);
471474

@@ -478,6 +481,7 @@ InFlightDiagnostic::wrapIn(const Diagnostic &wrapper) {
478481
// Overwrite the ID and argument with those from the wrapper.
479482
Engine->getActiveDiagnostic().ID = wrapper.ID;
480483
Engine->getActiveDiagnostic().Args = wrapper.Args;
484+
// Intentionally keeping the original GroupID here
481485

482486
// Set the argument to the diagnostic being wrapped.
483487
assert(wrapper.getArgs().front().getKind() == DiagnosticArgumentKind::Diagnostic);
@@ -1294,7 +1298,8 @@ void DiagnosticEngine::forwardTentativeDiagnosticsTo(
12941298
}
12951299

12961300
std::optional<DiagnosticInfo>
1297-
DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
1301+
DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic,
1302+
bool includeDiagnosticName) {
12981303
auto behavior = state.determineBehavior(diagnostic);
12991304
if (behavior == DiagnosticBehavior::Ignore)
13001305
return std::nullopt;
@@ -1347,12 +1352,19 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic) {
13471352
}
13481353
}
13491354

1350-
return DiagnosticInfo(
1351-
diagnostic.getID(), loc, toDiagnosticKind(behavior),
1352-
diagnosticStringFor(diagnostic.getID(), getPrintDiagnosticNamesMode()),
1353-
diagnostic.getArgs(), Category, getDefaultDiagnosticLoc(),
1354-
/*child note info*/ {}, diagnostic.getRanges(), fixIts,
1355-
diagnostic.isChildNote());
1355+
llvm::StringRef format;
1356+
if (includeDiagnosticName)
1357+
format =
1358+
diagnosticStringWithNameFor(diagnostic.getID(), diagnostic.getGroupID(),
1359+
getPrintDiagnosticNamesMode());
1360+
else
1361+
format = diagnosticStringFor(diagnostic.getID());
1362+
1363+
return DiagnosticInfo(diagnostic.getID(), loc, toDiagnosticKind(behavior),
1364+
format, diagnostic.getArgs(), Category,
1365+
getDefaultDiagnosticLoc(),
1366+
/*child note info*/ {}, diagnostic.getRanges(), fixIts,
1367+
diagnostic.isChildNote());
13561368
}
13571369

13581370
static DeclName
@@ -1462,7 +1474,9 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) {
14621474
ArrayRef<Diagnostic> childNotes = diagnostic.getChildNotes();
14631475
std::vector<Diagnostic> extendedChildNotes;
14641476

1465-
if (auto info = diagnosticInfoForDiagnostic(diagnostic)) {
1477+
if (auto info =
1478+
diagnosticInfoForDiagnostic(diagnostic,
1479+
/* includeDiagnosticName= */ true)) {
14661480
// If the diagnostic location is within a buffer containing generated
14671481
// source code, add child notes showing where the generation occurred.
14681482
// We need to avoid doing this if this is itself a child note, as otherwise
@@ -1478,7 +1492,9 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) {
14781492

14791493
SmallVector<DiagnosticInfo, 1> childInfo;
14801494
for (unsigned i : indices(childNotes)) {
1481-
auto child = diagnosticInfoForDiagnostic(childNotes[i]);
1495+
auto child =
1496+
diagnosticInfoForDiagnostic(childNotes[i],
1497+
/* includeDiagnosticName= */ true);
14821498
assert(child);
14831499
assert(child->Kind == DiagnosticKind::Note &&
14841500
"Expected child diagnostics to all be notes?!");
@@ -1516,12 +1532,18 @@ DiagnosticKind DiagnosticEngine::declaredDiagnosticKindFor(const DiagID id) {
15161532
return storedDiagnosticInfos[(unsigned)id].kind;
15171533
}
15181534

1519-
llvm::StringRef DiagnosticEngine::diagnosticStringFor(
1520-
const DiagID id, PrintDiagnosticNamesMode printDiagnosticNamesMode) {
1535+
llvm::StringRef DiagnosticEngine::diagnosticStringFor(DiagID id) {
15211536
llvm::StringRef message = diagnosticStrings[(unsigned)id];
15221537
if (auto localizationProducer = localization.get()) {
15231538
message = localizationProducer->getMessageOr(id, message);
15241539
}
1540+
return message;
1541+
}
1542+
1543+
llvm::StringRef DiagnosticEngine::diagnosticStringWithNameFor(
1544+
DiagID id, DiagGroupID groupID,
1545+
PrintDiagnosticNamesMode printDiagnosticNamesMode) {
1546+
auto message = diagnosticStringFor(id);
15251547
auto formatMessageWithName = [&](StringRef message, StringRef name) {
15261548
const int additionalCharsLength = 3; // ' ', '[', ']'
15271549
std::string messageWithName;
@@ -1540,7 +1562,6 @@ llvm::StringRef DiagnosticEngine::diagnosticStringFor(
15401562
message = formatMessageWithName(message, diagnosticIDStringFor(id));
15411563
break;
15421564
case PrintDiagnosticNamesMode::Group:
1543-
auto groupID = storedDiagnosticInfos[(unsigned)id].groupID;
15441565
if (groupID != DiagGroupID::no_group) {
15451566
message =
15461567
formatMessageWithName(message, getDiagGroupInfoByID(groupID).name);

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, PrintDiagnosticNamesMode::None);
70+
auto format = Engine.diagnosticStringFor(id);
7171
DiagnosticEngine::formatDiagnosticText(Out, format, DiagArgs);
7272
severity = getSeverity(Engine.declaredDiagnosticKindFor(id));
7373

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -977,8 +977,8 @@ class ModuleWriter {
977977
const_cast<ValueDecl *>(vd));
978978
// Emit a specific unavailable message when we know why a decl can't be
979979
// exposed, or a generic message otherwise.
980-
auto diagString = M.getASTContext().Diags.diagnosticStringFor(
981-
diag.getID(), PrintDiagnosticNamesMode::None);
980+
auto diagString =
981+
M.getASTContext().Diags.diagnosticStringFor(diag.getID());
982982
DiagnosticEngine::formatDiagnosticText(os, diagString, diag.getArgs(),
983983
DiagnosticFormatOptions());
984984
os << "\");\n";

0 commit comments

Comments
 (0)