Skip to content

Commit 1d8ca50

Browse files
committed
[Diagnostics] Add educational notes into serialized diagnostics
Use flag record (currently unused) to emit semi-colon separated list of paths to educational notes associated with a diagnostic. Resolves: rdar://118993780
1 parent d270dad commit 1d8ca50

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

lib/Frontend/SerializedDiagnosticConsumer.cpp

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,8 @@ struct SharedState : llvm::RefCountedBase<SharedState> {
8787
/// The collection of categories used.
8888
llvm::DenseMap<const char *, unsigned> Categories;
8989

90-
using DiagFlagsTy =
91-
llvm::DenseMap<const void *, std::pair<unsigned, StringRef>>;
92-
93-
/// Map for uniquing strings.
94-
DiagFlagsTy DiagFlags;
90+
/// The collection of flags used.
91+
llvm::StringMap<unsigned> Flags;
9592

9693
/// Whether we have already started emission of any DIAG blocks. Once
9794
/// this becomes \c true, we never close a DIAG block until we know that we're
@@ -198,6 +195,14 @@ class SerializedDiagnosticConsumer : public DiagnosticConsumer {
198195
// Record identifier for the category.
199196
unsigned getEmitCategory(StringRef Category);
200197

198+
/// Emit a flag record that contains a semi-colon separated
199+
/// list of all of the educational notes associated with the
200+
/// diagnostic or `0` if there are no notes.
201+
///
202+
/// \returns a flag record identifier that could be embedded in
203+
/// other records.
204+
unsigned emitEducationalNotes(const DiagnosticInfo &info);
205+
201206
/// Add a source location to a record.
202207
void addLocToRecord(SourceLoc Loc,
203208
SourceManager &SM,
@@ -319,6 +324,34 @@ unsigned SerializedDiagnosticConsumer::getEmitCategory(StringRef Category) {
319324
return entry;
320325
}
321326

327+
unsigned
328+
SerializedDiagnosticConsumer::emitEducationalNotes(const DiagnosticInfo &Info) {
329+
if (Info.EducationalNotePaths.empty())
330+
return 0;
331+
332+
SmallString<32> scratch;
333+
interleave(
334+
Info.EducationalNotePaths,
335+
[&scratch](const auto &notePath) { scratch += notePath; },
336+
[&scratch] { scratch += ';'; });
337+
338+
StringRef paths = scratch.str();
339+
340+
unsigned &recordID = State->Flags[paths];
341+
if (recordID)
342+
return recordID;
343+
344+
recordID = State->Flags.size();
345+
346+
RecordData Record;
347+
Record.push_back(RECORD_DIAG_FLAG);
348+
Record.push_back(recordID);
349+
Record.push_back(paths.size());
350+
State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_DIAG_FLAG), Record,
351+
paths.data());
352+
return recordID;
353+
}
354+
322355
void SerializedDiagnosticConsumer::addLocToRecord(SourceLoc Loc,
323356
SourceManager &SM,
324357
StringRef Filename,
@@ -572,8 +605,10 @@ emitDiagnosticMessage(SourceManager &SM,
572605
Record.push_back(0);
573606
}
574607

575-
// FIXME: Swift diagnostics currently have no flags.
576-
Record.push_back(0);
608+
// Use "flags" slot to emit a semi-colon separated list of
609+
// educational notes. If there are no notes associated with
610+
// this diagnostic `0` placeholder would be emitted instead.
611+
Record.push_back(emitEducationalNotes(Info));
577612

578613
// Emit the message.
579614
Record.push_back(Text.size());
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// not %target-swift-frontend -no-color-diagnostics -print-educational-notes -diagnostic-documentation-path %S/test-docs/ -typecheck %s
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: not %target-swift-frontend -typecheck -no-color-diagnostics -print-educational-notes -diagnostic-documentation-path %S/test-docs/ -serialize-diagnostics-path %t/serialized.dia %s
5+
// RUN: c-index-test -read-diagnostics %t/serialized.dia > %t/serialized.txt 2>&1
6+
// RUN: %FileCheck %s < %t/serialized.txt
7+
8+
typealias Fn = () -> ()
9+
extension Fn {}
10+
// CHECK: [[@LINE-1]]:1: error: non-nominal type 'Fn' (aka '() -> ()') cannot be extended [{{.*}}/diagnostics/test-docs/nominal-types.md] []
11+
12+
13+
// Shares the flag record with `Fn`
14+
typealias Dup = () -> ()
15+
extension Dup {}
16+
// CHECK: [[@LINE-1]]:1: error: non-nominal type 'Dup' (aka '() -> ()') cannot be extended [{{.*}}/diagnostics/test-docs/nominal-types.md] []
17+
18+
do {
19+
func noNote(_: Int) {}
20+
noNote("Hello")
21+
// CHECK: [[@LINE-1]]:10: error: cannot convert value of type 'String' to expected argument type 'Int' [] []
22+
}

0 commit comments

Comments
 (0)