mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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).
This commit is contained in:
@@ -46,6 +46,10 @@ public:
|
||||
void enqueueDiagnostic(SourceManager &SM, const DiagnosticInfo &Info,
|
||||
unsigned innermostBufferID);
|
||||
|
||||
/// Emit a single diagnostic without location information.
|
||||
void emitDiagnosticWithoutLocation(
|
||||
const DiagnosticInfo &Info, llvm::raw_ostream &out, bool forceColors);
|
||||
|
||||
/// Flush all enqueued diagnostics.
|
||||
void flush(llvm::raw_ostream &OS, bool includeTrailingBreak,
|
||||
bool forceColors);
|
||||
|
||||
@@ -35,6 +35,14 @@ void swift_ASTGen_addQueuedDiagnostic(
|
||||
const BridgedCharSourceRange *_Nullable highlightRanges,
|
||||
ptrdiff_t numHighlightRanges,
|
||||
BridgedArrayRef /*BridgedFixIt*/ fixIts);
|
||||
void swift_ASTGen_renderSingleDiagnostic(
|
||||
void *_Nonnull state,
|
||||
BridgedStringRef text,
|
||||
BridgedDiagnosticSeverity severity,
|
||||
BridgedStringRef categoryName,
|
||||
BridgedStringRef documentationPath,
|
||||
ssize_t colorize,
|
||||
BridgedStringRef *_Nonnull renderedString);
|
||||
void swift_ASTGen_renderQueuedDiagnostics(
|
||||
void *_Nonnull queued, ssize_t contextSize, ssize_t colorize,
|
||||
BridgedStringRef *_Nonnull renderedString);
|
||||
|
||||
@@ -26,6 +26,22 @@
|
||||
using namespace swift;
|
||||
|
||||
#if SWIFT_BUILD_SWIFT_SYNTAX
|
||||
static BridgedDiagnosticSeverity bridgeDiagnosticSeverity(DiagnosticKind kind) {
|
||||
switch (kind) {
|
||||
case DiagnosticKind::Error:
|
||||
return BridgedDiagnosticSeverity::BridgedError;
|
||||
|
||||
case DiagnosticKind::Warning:
|
||||
return BridgedDiagnosticSeverity::BridgedWarning;
|
||||
|
||||
case DiagnosticKind::Remark:
|
||||
return BridgedDiagnosticSeverity::BridgedRemark;
|
||||
|
||||
case DiagnosticKind::Note:
|
||||
return BridgedDiagnosticSeverity::BridgedNote;
|
||||
}
|
||||
}
|
||||
|
||||
/// Enqueue a diagnostic with ASTGen's diagnostic rendering.
|
||||
static void addQueueDiagnostic(void *queuedDiagnostics,
|
||||
void *perFrontendState,
|
||||
@@ -37,24 +53,7 @@ static void addQueueDiagnostic(void *queuedDiagnostics,
|
||||
info.FormatArgs);
|
||||
}
|
||||
|
||||
BridgedDiagnosticSeverity severity;
|
||||
switch (info.Kind) {
|
||||
case DiagnosticKind::Error:
|
||||
severity = BridgedDiagnosticSeverity::BridgedError;
|
||||
break;
|
||||
|
||||
case DiagnosticKind::Warning:
|
||||
severity = BridgedDiagnosticSeverity::BridgedWarning;
|
||||
break;
|
||||
|
||||
case DiagnosticKind::Remark:
|
||||
severity = BridgedDiagnosticSeverity::BridgedRemark;
|
||||
break;
|
||||
|
||||
case DiagnosticKind::Note:
|
||||
severity = BridgedDiagnosticSeverity::BridgedNote;
|
||||
break;
|
||||
}
|
||||
BridgedDiagnosticSeverity severity = bridgeDiagnosticSeverity(info.Kind);
|
||||
|
||||
// Map the highlight ranges.
|
||||
SmallVector<BridgedCharSourceRange, 2> highlightRanges;
|
||||
@@ -87,6 +86,39 @@ static void addQueueDiagnostic(void *queuedDiagnostics,
|
||||
}
|
||||
}
|
||||
|
||||
void DiagnosticBridge::emitDiagnosticWithoutLocation(
|
||||
const DiagnosticInfo &info, llvm::raw_ostream &out, bool forceColors) {
|
||||
ASSERT(queuedDiagnostics == nullptr);
|
||||
|
||||
// If we didn't have per-frontend state before, create it now.
|
||||
if (!perFrontendState) {
|
||||
perFrontendState = swift_ASTGen_createPerFrontendDiagnosticState();
|
||||
}
|
||||
|
||||
llvm::SmallString<256> text;
|
||||
{
|
||||
llvm::raw_svector_ostream out(text);
|
||||
DiagnosticEngine::formatDiagnosticText(out, info.FormatString,
|
||||
info.FormatArgs);
|
||||
}
|
||||
|
||||
BridgedDiagnosticSeverity severity = bridgeDiagnosticSeverity(info.Kind);
|
||||
|
||||
BridgedStringRef bridgedRenderedString{nullptr, 0};
|
||||
swift_ASTGen_renderSingleDiagnostic(
|
||||
perFrontendState, text.str(), severity, info.Category,
|
||||
llvm::StringRef(info.CategoryDocumentationURL), forceColors ? 1 : 0,
|
||||
&bridgedRenderedString);
|
||||
|
||||
auto renderedString = bridgedRenderedString.unbridged();
|
||||
if (renderedString.data()) {
|
||||
out << "<unknown>:0: ";
|
||||
out.write(renderedString.data(), renderedString.size());
|
||||
swift_ASTGen_freeBridgedString(renderedString);
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void DiagnosticBridge::enqueueDiagnostic(SourceManager &SM,
|
||||
const DiagnosticInfo &Info,
|
||||
unsigned innermostBufferID) {
|
||||
|
||||
@@ -425,6 +425,60 @@ public func addQueuedDiagnostic(
|
||||
queuedDiagnostics.pointee.grouped.addDiagnostic(diagnostic)
|
||||
}
|
||||
|
||||
/// Render a single diagnostic that has no source location information.
|
||||
@_cdecl("swift_ASTGen_renderSingleDiagnostic")
|
||||
public func renderSingleDiagnostic(
|
||||
perFrontendDiagnosticStatePtr: UnsafeMutableRawPointer,
|
||||
text: BridgedStringRef,
|
||||
severity: BridgedDiagnosticSeverity,
|
||||
categoryName: BridgedStringRef,
|
||||
documentationPath: BridgedStringRef,
|
||||
colorize: Int,
|
||||
renderedStringOutPtr: UnsafeMutablePointer<BridgedStringRef>
|
||||
) {
|
||||
let diagnosticState = perFrontendDiagnosticStatePtr.assumingMemoryBound(
|
||||
to: PerFrontendDiagnosticState.self
|
||||
)
|
||||
|
||||
let documentationPath = String(bridged: documentationPath)
|
||||
let documentationURL: String? = if !documentationPath.isEmpty {
|
||||
// If this looks doesn't look like a URL, prepend file://.
|
||||
documentationPath.looksLikeURL ? documentationPath : "file://\(documentationPath)"
|
||||
} else {
|
||||
nil
|
||||
}
|
||||
|
||||
let categoryName = String(bridged: categoryName)
|
||||
// If the data comes from serialized diagnostics, it's possible that
|
||||
// the category name is empty because StringRef() is serialized into
|
||||
// an empty string.
|
||||
let category: DiagnosticCategory? = if !categoryName.isEmpty {
|
||||
DiagnosticCategory(
|
||||
name: categoryName,
|
||||
documentationURL: documentationURL
|
||||
)
|
||||
} else {
|
||||
nil
|
||||
}
|
||||
|
||||
// Note that we referenced this category.
|
||||
if let category {
|
||||
diagnosticState.pointee.referencedCategories.insert(category)
|
||||
}
|
||||
|
||||
let formatter = DiagnosticsFormatter(colorize: colorize != 0)
|
||||
|
||||
let renderedStr = formatter.formattedMessage(
|
||||
SimpleDiagnostic(
|
||||
message: String(bridged: text),
|
||||
severity: severity.asSeverity,
|
||||
category: category
|
||||
)
|
||||
)
|
||||
|
||||
renderedStringOutPtr.pointee = allocateBridgedString(renderedStr)
|
||||
}
|
||||
|
||||
/// Render the queued diagnostics into a UTF-8 string.
|
||||
@_cdecl("swift_ASTGen_renderQueuedDiagnostics")
|
||||
public func renderQueuedDiagnostics(
|
||||
|
||||
@@ -48,20 +48,20 @@ void PrintingDiagnosticConsumer::handleDiagnostic(SourceManager &SM,
|
||||
#if SWIFT_BUILD_SWIFT_SYNTAX
|
||||
// Use the swift-syntax formatter.
|
||||
auto bufferStack = DiagnosticBridge::getSourceBufferStack(SM, Info.Loc);
|
||||
if (!bufferStack.empty()) {
|
||||
if (Info.Kind != DiagnosticKind::Note)
|
||||
DiagBridge.flush(Stream, /*includeTrailingBreak=*/true,
|
||||
/*forceColors=*/ForceColors);
|
||||
if (Info.Kind != DiagnosticKind::Note || bufferStack.empty())
|
||||
DiagBridge.flush(Stream, /*includeTrailingBreak=*/true,
|
||||
/*forceColors=*/ForceColors);
|
||||
|
||||
if (bufferStack.empty()) {
|
||||
DiagBridge.emitDiagnosticWithoutLocation(Info, Stream, ForceColors);
|
||||
} else {
|
||||
DiagBridge.enqueueDiagnostic(SM, Info, bufferStack.front());
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
#else
|
||||
// Fall through when we don't have the new diagnostics renderer available.
|
||||
// This also happens if the location of the diagnostic is invalid, because
|
||||
// the new rendered cannot cope with that.
|
||||
LLVM_FALLTHROUGH;
|
||||
#endif
|
||||
}
|
||||
|
||||
case DiagnosticOptions::FormattingStyle::LLVM:
|
||||
@@ -215,4 +215,6 @@ PrintingDiagnosticConsumer::PrintingDiagnosticConsumer(
|
||||
llvm::raw_ostream &stream)
|
||||
: Stream(stream) {}
|
||||
|
||||
PrintingDiagnosticConsumer::~PrintingDiagnosticConsumer() {}
|
||||
PrintingDiagnosticConsumer::~PrintingDiagnosticConsumer() {
|
||||
flush();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user