diff --git a/swift/extractor/invocation/SwiftDiagnosticsConsumer.cpp b/swift/extractor/invocation/SwiftDiagnosticsConsumer.cpp index 9d5aa4654d5..0cc5959aebc 100644 --- a/swift/extractor/invocation/SwiftDiagnosticsConsumer.cpp +++ b/swift/extractor/invocation/SwiftDiagnosticsConsumer.cpp @@ -1,5 +1,5 @@ #include "swift/extractor/invocation/SwiftDiagnosticsConsumer.h" -#include "swift/extractor/trap/generated/TrapEntries.h" +#include "swift/extractor/trap/generated/TrapClasses.h" #include "swift/extractor/trap/TrapDomain.h" #include "swift/extractor/infra/SwiftDiagnosticKind.h" @@ -11,15 +11,37 @@ using namespace codeql; +namespace { +struct DisplayLoc { + llvm::StringRef file; + unsigned line; + unsigned column; + + static DisplayLoc from(swift::SourceManager& sourceManager, swift::SourceLoc loc) { + if (loc.isInvalid()) { + return {"", 0, 0}; + } + auto file = sourceManager.getDisplayNameForLoc(loc); + auto [line, column] = sourceManager.getLineAndColumnInBuffer(loc); + return {file, line, column}; + } +}; + +} // namespace + void SwiftDiagnosticsConsumer::handleDiagnostic(swift::SourceManager& sourceManager, const swift::DiagnosticInfo& diagInfo) { - auto message = getDiagMessage(sourceManager, diagInfo); - DiagnosticsTrap diag{}; - diag.id = trap.createTypedLabel(); + if (diagInfo.IsChildNote) return; + Diagnostics diag{trap.createTypedLabel()}; diag.kind = translateDiagnosticsKind(diagInfo.Kind); - diag.text = message; + diag.text = getDiagMessage(sourceManager, diagInfo); trap.emit(diag); locationExtractor.attachLocation(sourceManager, diagInfo, diag.id); + + forwardToLog(sourceManager, diagInfo, diag.text); + for (const auto& child : diagInfo.ChildDiagnosticInfo) { + forwardToLog(sourceManager, *child); + } } std::string SwiftDiagnosticsConsumer::getDiagMessage(swift::SourceManager& sourceManager, @@ -29,3 +51,28 @@ std::string SwiftDiagnosticsConsumer::getDiagMessage(swift::SourceManager& sourc swift::DiagnosticEngine::formatDiagnosticText(out, diagInfo.FormatString, diagInfo.FormatArgs); return text.str().str(); } + +void SwiftDiagnosticsConsumer::forwardToLog(swift::SourceManager& sourceManager, + const swift::DiagnosticInfo& diagInfo, + const std::string& message) { + auto [file, line, column] = DisplayLoc::from(sourceManager, diagInfo.Loc); + using Kind = swift::DiagnosticKind; + switch (diagInfo.Kind) { + case Kind::Error: + LOG_ERROR("{}:{}:{} {}", file, line, column, message); + break; + case Kind::Warning: + LOG_WARNING("{}:{}:{} {}", file, line, column, message); + break; + case Kind::Remark: + LOG_INFO("{}:{}:{} {}", file, line, column, message); + break; + case Kind::Note: + LOG_DEBUG("{}:{}:{} {}", file, line, column, message); + break; + default: + LOG_ERROR("unknown diagnostic kind {}, {}:{}:{} {}", diagInfo.Kind, file, line, column, + message); + break; + } +} diff --git a/swift/extractor/invocation/SwiftDiagnosticsConsumer.h b/swift/extractor/invocation/SwiftDiagnosticsConsumer.h index c85233348fd..e2817981f76 100644 --- a/swift/extractor/invocation/SwiftDiagnosticsConsumer.h +++ b/swift/extractor/invocation/SwiftDiagnosticsConsumer.h @@ -2,6 +2,7 @@ #include #include "swift/extractor/infra/SwiftLocationExtractor.h" +#include "swift/logging/SwiftLogging.h" namespace codeql { @@ -17,8 +18,17 @@ class SwiftDiagnosticsConsumer : public swift::DiagnosticConsumer { private: static std::string getDiagMessage(swift::SourceManager& sourceManager, const swift::DiagnosticInfo& diagInfo); + void forwardToLog(swift::SourceManager& sourceManager, + const swift::DiagnosticInfo& diagInfo, + const std::string& message); + + void forwardToLog(swift::SourceManager& sourceManager, const swift::DiagnosticInfo& diagInfo) { + forwardToLog(sourceManager, diagInfo, getDiagMessage(sourceManager, diagInfo)); + } + TrapDomain& trap; SwiftLocationExtractor locationExtractor; + Logger logger{"compiler"}; }; } // namespace codeql diff --git a/swift/extractor/main.cpp b/swift/extractor/main.cpp index 4f1dd990be9..0abb5404035 100644 --- a/swift/extractor/main.cpp +++ b/swift/extractor/main.cpp @@ -91,6 +91,8 @@ class Observer : public swift::FrontendObserver { } void configuredCompiler(swift::CompilerInstance& instance) override { + // remove default consumers to avoid double messaging + instance.getDiags().takeConsumers(); instance.addDiagnosticConsumer(&diagConsumer); }