Skip to content

Commit eb5f5dd

Browse files
committed
[Diagnostics] Use the swift-syntax formatting for invalid source locations, too
The diagnostics formatter from swift-syntax previously only handled fully-formed diagnostics anchored at a particular syntax node. Therefore, the compiler would fall back to the existing LLVM-based diagnostic formatter for diagnostics that had no source location. Adopt new API in the swift-syntax diagnostics formatter that renders a diagnostic message without requiring source location information, so that we consistently use the swift-syntax formatter when it is selected (which is the default).
1 parent 9eebee8 commit eb5f5dd

File tree

7 files changed

+133
-28
lines changed

7 files changed

+133
-28
lines changed

include/swift/AST/DiagnosticBridge.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ class DiagnosticBridge {
4646
void enqueueDiagnostic(SourceManager &SM, const DiagnosticInfo &Info,
4747
unsigned innermostBufferID);
4848

49+
/// Emit a single diagnostic without location information.
50+
void emitSingleDiagnostic(
51+
const DiagnosticInfo &Info, llvm::raw_ostream &out, bool forceColors);
52+
4953
/// Flush all enqueued diagnostics.
5054
void flush(llvm::raw_ostream &OS, bool includeTrailingBreak,
5155
bool forceColors);

include/swift/Bridging/ASTGen.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ void swift_ASTGen_addQueuedDiagnostic(
3535
const BridgedCharSourceRange *_Nullable highlightRanges,
3636
ptrdiff_t numHighlightRanges,
3737
BridgedArrayRef /*BridgedFixIt*/ fixIts);
38+
void swift_ASTGen_renderSingleDiagnostic(
39+
void *_Nonnull state,
40+
BridgedStringRef text,
41+
BridgedDiagnosticSeverity severity,
42+
BridgedStringRef categoryName,
43+
BridgedStringRef documentationPath,
44+
ssize_t colorize,
45+
BridgedStringRef *_Nonnull renderedString);
3846
void swift_ASTGen_renderQueuedDiagnostics(
3947
void *_Nonnull queued, ssize_t contextSize, ssize_t colorize,
4048
BridgedStringRef *_Nonnull renderedString);

include/swift/Frontend/PrintingDiagnosticConsumer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class PrintingDiagnosticConsumer : public DiagnosticConsumer {
3535
bool EmitMacroExpansionFiles = false;
3636
bool DidErrorOccur = false;
3737
DiagnosticOptions::FormattingStyle FormattingStyle =
38-
DiagnosticOptions::FormattingStyle::LLVM;
38+
DiagnosticOptions::FormattingStyle::Swift;
3939
bool SuppressOutput = false;
4040

4141
#if SWIFT_BUILD_SWIFT_SYNTAX

lib/AST/DiagnosticBridge.cpp

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@
2626
using namespace swift;
2727

2828
#if SWIFT_BUILD_SWIFT_SYNTAX
29+
static BridgedDiagnosticSeverity bridgeDiagnosticSeverity(DiagnosticKind kind) {
30+
switch (kind) {
31+
case DiagnosticKind::Error:
32+
return BridgedDiagnosticSeverity::BridgedError;
33+
34+
case DiagnosticKind::Warning:
35+
return BridgedDiagnosticSeverity::BridgedWarning;
36+
37+
case DiagnosticKind::Remark:
38+
return BridgedDiagnosticSeverity::BridgedRemark;
39+
40+
case DiagnosticKind::Note:
41+
return BridgedDiagnosticSeverity::BridgedNote;
42+
}
43+
}
44+
2945
/// Enqueue a diagnostic with ASTGen's diagnostic rendering.
3046
static void addQueueDiagnostic(void *queuedDiagnostics,
3147
void *perFrontendState,
@@ -37,24 +53,7 @@ static void addQueueDiagnostic(void *queuedDiagnostics,
3753
info.FormatArgs);
3854
}
3955

40-
BridgedDiagnosticSeverity severity;
41-
switch (info.Kind) {
42-
case DiagnosticKind::Error:
43-
severity = BridgedDiagnosticSeverity::BridgedError;
44-
break;
45-
46-
case DiagnosticKind::Warning:
47-
severity = BridgedDiagnosticSeverity::BridgedWarning;
48-
break;
49-
50-
case DiagnosticKind::Remark:
51-
severity = BridgedDiagnosticSeverity::BridgedRemark;
52-
break;
53-
54-
case DiagnosticKind::Note:
55-
severity = BridgedDiagnosticSeverity::BridgedNote;
56-
break;
57-
}
56+
BridgedDiagnosticSeverity severity = bridgeDiagnosticSeverity(info.Kind);
5857

5958
// Map the highlight ranges.
6059
SmallVector<BridgedCharSourceRange, 2> highlightRanges;
@@ -87,6 +86,37 @@ static void addQueueDiagnostic(void *queuedDiagnostics,
8786
}
8887
}
8988

89+
void DiagnosticBridge::emitSingleDiagnostic(
90+
const DiagnosticInfo &info, llvm::raw_ostream &out, bool forceColors) {
91+
// If we didn't have per-frontend state before, create it now.
92+
if (!perFrontendState) {
93+
perFrontendState = swift_ASTGen_createPerFrontendDiagnosticState();
94+
}
95+
96+
llvm::SmallString<256> text;
97+
{
98+
llvm::raw_svector_ostream out(text);
99+
DiagnosticEngine::formatDiagnosticText(out, info.FormatString,
100+
info.FormatArgs);
101+
}
102+
103+
BridgedDiagnosticSeverity severity = bridgeDiagnosticSeverity(info.Kind);
104+
105+
BridgedStringRef bridgedRenderedString{nullptr, 0};
106+
swift_ASTGen_renderSingleDiagnostic(
107+
perFrontendState, text.str(), severity, info.Category,
108+
llvm::StringRef(info.CategoryDocumentationURL), forceColors ? 1 : 0,
109+
&bridgedRenderedString);
110+
111+
auto renderedString = bridgedRenderedString.unbridged();
112+
if (renderedString.data()) {
113+
out << "<unknown>:0: ";
114+
out.write(renderedString.data(), renderedString.size());
115+
swift_ASTGen_freeBridgedString(renderedString);
116+
out << "\n";
117+
}
118+
}
119+
90120
void DiagnosticBridge::enqueueDiagnostic(SourceManager &SM,
91121
const DiagnosticInfo &Info,
92122
unsigned innermostBufferID) {

lib/ASTGen/Sources/ASTGen/DiagnosticsBridge.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,60 @@ public func addQueuedDiagnostic(
425425
queuedDiagnostics.pointee.grouped.addDiagnostic(diagnostic)
426426
}
427427

428+
/// Render a single diagnostic that has no source location information.
429+
@_cdecl("swift_ASTGen_renderSingleDiagnostic")
430+
public func renderSingleDiagnostic(
431+
perFrontendDiagnosticStatePtr: UnsafeMutableRawPointer,
432+
text: BridgedStringRef,
433+
severity: BridgedDiagnosticSeverity,
434+
categoryName: BridgedStringRef,
435+
documentationPath: BridgedStringRef,
436+
colorize: Int,
437+
renderedStringOutPtr: UnsafeMutablePointer<BridgedStringRef>
438+
) {
439+
let diagnosticState = perFrontendDiagnosticStatePtr.assumingMemoryBound(
440+
to: PerFrontendDiagnosticState.self
441+
)
442+
443+
let documentationPath = String(bridged: documentationPath)
444+
let documentationURL: String? = if !documentationPath.isEmpty {
445+
// If this looks doesn't look like a URL, prepend file://.
446+
documentationPath.looksLikeURL ? documentationPath : "file://\(documentationPath)"
447+
} else {
448+
nil
449+
}
450+
451+
let categoryName = String(bridged: categoryName)
452+
// If the data comes from serialized diagnostics, it's possible that
453+
// the category name is empty because StringRef() is serialized into
454+
// an empty string.
455+
let category: DiagnosticCategory? = if !categoryName.isEmpty {
456+
DiagnosticCategory(
457+
name: categoryName,
458+
documentationURL: documentationURL
459+
)
460+
} else {
461+
nil
462+
}
463+
464+
// Note that we referenced this category.
465+
if let category {
466+
diagnosticState.pointee.referencedCategories.insert(category)
467+
}
468+
469+
let formatter = DiagnosticsFormatter(colorize: colorize != 0)
470+
471+
let renderedStr = formatter.formattedMessage(
472+
SimpleDiagnostic(
473+
message: String(bridged: text),
474+
severity: severity.asSeverity,
475+
category: category
476+
)
477+
)
478+
479+
renderedStringOutPtr.pointee = allocateBridgedString(renderedStr)
480+
}
481+
428482
/// Render the queued diagnostics into a UTF-8 string.
429483
@_cdecl("swift_ASTGen_renderQueuedDiagnostics")
430484
public func renderQueuedDiagnostics(

lib/Frontend/PrintingDiagnosticConsumer.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,20 @@ void PrintingDiagnosticConsumer::handleDiagnostic(SourceManager &SM,
4848
#if SWIFT_BUILD_SWIFT_SYNTAX
4949
// Use the swift-syntax formatter.
5050
auto bufferStack = DiagnosticBridge::getSourceBufferStack(SM, Info.Loc);
51-
if (!bufferStack.empty()) {
52-
if (Info.Kind != DiagnosticKind::Note)
53-
DiagBridge.flush(Stream, /*includeTrailingBreak=*/true,
54-
/*forceColors=*/ForceColors);
51+
if (Info.Kind != DiagnosticKind::Note || bufferStack.empty())
52+
DiagBridge.flush(Stream, /*includeTrailingBreak=*/true,
53+
/*forceColors=*/ForceColors);
5554

55+
if (bufferStack.empty()) {
56+
DiagBridge.emitSingleDiagnostic(Info, Stream, ForceColors);
57+
} else {
5658
DiagBridge.enqueueDiagnostic(SM, Info, bufferStack.front());
57-
break;
5859
}
59-
#endif
60-
60+
return;
61+
#else
6162
// Fall through when we don't have the new diagnostics renderer available.
62-
// This also happens if the location of the diagnostic is invalid, because
63-
// the new rendered cannot cope with that.
6463
LLVM_FALLTHROUGH;
64+
#endif
6565
}
6666

6767
case DiagnosticOptions::FormattingStyle::LLVM:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-frontend -typecheck -strict-memory-safety -Ounchecked %s 2>&1 | %FileCheck %s -check-prefix CHECK
2+
// REQUIRES: swift_swift_parser
3+
4+
// This test ensures that we get category footnotes even from diagnostics with
5+
// no source location information.
6+
func nothing() { }
7+
8+
// CHECK: warning: '-Ounchecked' is not memory-safe
9+
// CHECK: [#StrictMemorySafety]: <https://{{.*}}strict-memory-safety>

0 commit comments

Comments
 (0)