Skip to content

Commit 0997a7e

Browse files
authored
Merge pull request #79688 from DougGregor/diagnostic-ref-footnotes
[Diagnostics] Reference markdown files for educational notes and diagnostic group documentation
2 parents 77d18a8 + 398e1ad commit 0997a7e

File tree

5 files changed

+82
-3
lines changed

5 files changed

+82
-3
lines changed

include/swift/Bridging/ASTGen.h

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ void swift_ASTGen_addQueuedSourceFile(
2828
void swift_ASTGen_addQueuedDiagnostic(
2929
void *_Nonnull queued, const char *_Nonnull text, ptrdiff_t textLength,
3030
BridgedDiagnosticSeverity severity, const void *_Nullable sourceLoc,
31+
const char *_Nullable categoryName, ptrdiff_t categoryNameLength,
32+
const char *_Nullable documentationPath,
33+
ptrdiff_t documentationPathLength,
3134
const void *_Nullable *_Nullable highlightRanges,
3235
ptrdiff_t numHighlightRanges);
3336
void swift_ASTGen_renderQueuedDiagnostics(

lib/AST/DiagnosticBridge.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,17 @@ static void addQueueDiagnostic(void *queuedDiagnostics,
6464
highlightRanges.push_back(range.getEnd().getOpaquePointerValue());
6565
}
6666

67+
StringRef documentationPath;
68+
if (info.EducationalNotePaths.size() > 0)
69+
documentationPath = info.EducationalNotePaths[0];
70+
6771
// FIXME: Translate Fix-Its.
6872
swift_ASTGen_addQueuedDiagnostic(queuedDiagnostics, text.data(), text.size(),
6973
severity, info.Loc.getOpaquePointerValue(),
74+
info.Category.data(),
75+
info.Category.size(),
76+
documentationPath.data(),
77+
documentationPath.size(),
7078
highlightRanges.data(),
7179
highlightRanges.size() / 2);
7280
}

lib/AST/DiagnosticEngine.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,7 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic,
13561356

13571357
auto groupID = diagnostic.getGroupID();
13581358
StringRef Category;
1359+
const char * const *associatedNotes = nullptr;
13591360
if (isAPIDigesterBreakageDiagnostic(diagnostic.getID()))
13601361
Category = "api-digester-breaking-change";
13611362
else if (isNoUsageDiagnostic(diagnostic.getID()))
@@ -1364,6 +1365,10 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic,
13641365
Category = getDiagGroupInfoByID(groupID).name;
13651366
else if (isDeprecationDiagnostic(diagnostic.getID()))
13661367
Category = "deprecation";
1368+
else if ((associatedNotes = educationalNotes[(uint32_t)diagnostic.getID()]) &&
1369+
*associatedNotes) {
1370+
Category = llvm::sys::path::stem(*associatedNotes);
1371+
}
13671372

13681373
auto fixIts = diagnostic.getFixIts();
13691374
if (loc.isValid()) {

lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift

+64-1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ fileprivate struct SimpleDiagnostic: DiagnosticMessage {
165165

166166
let severity: DiagnosticSeverity
167167

168+
let category: DiagnosticCategory?
169+
168170
var diagnosticID: MessageID {
169171
.init(domain: "SwiftCompiler", id: "SimpleDiagnostic")
170172
}
@@ -237,6 +239,10 @@ public func addQueuedDiagnostic(
237239
textLength: Int,
238240
severity: BridgedDiagnosticSeverity,
239241
cLoc: BridgedSourceLoc,
242+
categoryName: UnsafePointer<UInt8>?,
243+
categoryLength: Int,
244+
documentationPath: UnsafePointer<UInt8>?,
245+
documentationPathLength: Int,
240246
highlightRangesPtr: UnsafePointer<BridgedSourceLoc>?,
241247
numHighlightRanges: Int
242248
) {
@@ -333,13 +339,43 @@ public func addQueuedDiagnostic(
333339
}
334340
}
335341

342+
let category: DiagnosticCategory? = categoryName.map { categoryNamePtr in
343+
let categoryNameBuffer = UnsafeBufferPointer(
344+
start: categoryNamePtr,
345+
count: categoryLength
346+
)
347+
let categoryName = String(decoding: categoryNameBuffer, as: UTF8.self)
348+
349+
let documentationURL = documentationPath.map { documentationPathPtr in
350+
let documentationPathBuffer = UnsafeBufferPointer(
351+
start: documentationPathPtr,
352+
count: documentationPathLength
353+
)
354+
355+
let documentationPath = String(decoding: documentationPathBuffer, as: UTF8.self)
356+
357+
// If this looks doesn't look like a URL, prepend file://.
358+
if !documentationPath.looksLikeURL {
359+
return "file://\(documentationPath)"
360+
}
361+
362+
return documentationPath
363+
}
364+
365+
return DiagnosticCategory(
366+
name: categoryName,
367+
documentationURL: documentationURL
368+
)
369+
}
370+
336371
let textBuffer = UnsafeBufferPointer(start: text, count: textLength)
337372
let diagnostic = Diagnostic(
338373
node: node,
339374
position: position,
340375
message: SimpleDiagnostic(
341376
message: String(decoding: textBuffer, as: UTF8.self),
342-
severity: severity.asSeverity
377+
severity: severity.asSeverity,
378+
category: category
343379
),
344380
highlights: highlights
345381
)
@@ -361,3 +397,30 @@ public func renderQueuedDiagnostics(
361397

362398
renderedStringOutPtr.pointee = allocateBridgedString(renderedStr)
363399
}
400+
401+
extension String {
402+
/// Simple check to determine whether the string looks like the start of a
403+
/// URL.
404+
fileprivate var looksLikeURL: Bool {
405+
var forwardSlashes: Int = 0
406+
for c in self {
407+
if c == "/" {
408+
forwardSlashes += 1
409+
if forwardSlashes > 2 {
410+
return true
411+
}
412+
413+
continue
414+
}
415+
416+
if c.isLetter || c.isNumber {
417+
forwardSlashes = 0
418+
continue
419+
}
420+
421+
return false
422+
}
423+
424+
return false
425+
}
426+
}

test/diagnostics/educational_notes_serialization.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
typealias Fn = () -> ()
99
extension Fn {}
10-
// CHECK: [[@LINE-1]]:1: error: non-nominal type 'Fn' (aka '() -> ()') cannot be extended [{{.*}}nominal-types.md] []
10+
// CHECK: [[@LINE-1]]:1: error: non-nominal type 'Fn' (aka '() -> ()') cannot be extended [{{.*}}nominal-types.md] [nominal-types]
1111

1212

1313
// Shares the flag record with `Fn`
1414
typealias Dup = () -> ()
1515
extension Dup {}
16-
// CHECK: [[@LINE-1]]:1: error: non-nominal type 'Dup' (aka '() -> ()') cannot be extended [{{.*}}nominal-types.md] []
16+
// CHECK: [[@LINE-1]]:1: error: non-nominal type 'Dup' (aka '() -> ()') cannot be extended [{{.*}}nominal-types.md] [nominal-types]
1717

1818
do {
1919
func noNote(_: Int) {}

0 commit comments

Comments
 (0)