diff --git a/include/swift/Basic/DiagnosticConsumer.h b/include/swift/AST/DiagnosticConsumer.h similarity index 89% rename from include/swift/Basic/DiagnosticConsumer.h rename to include/swift/AST/DiagnosticConsumer.h index 22d8cbcdf8f95..3ba2575397e6e 100644 --- a/include/swift/Basic/DiagnosticConsumer.h +++ b/include/swift/AST/DiagnosticConsumer.h @@ -23,6 +23,7 @@ #include "llvm/Support/SourceMgr.h" namespace swift { + class DiagnosticArgument; class SourceManager; enum class DiagID : uint32_t; @@ -87,11 +88,13 @@ class DiagnosticConsumer { /// /// \param Kind The severity of the diagnostic (error, warning, note). /// - /// \param Text The diagnostic text. + /// \param FormatArgs The diagnostic format string arguments. /// /// \param Info Extra information associated with the diagnostic. virtual void handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, StringRef Text, + DiagnosticKind Kind, + StringRef FormatString, + ArrayRef FormatArgs, const DiagnosticInfo &Info) = 0; }; @@ -99,7 +102,9 @@ class DiagnosticConsumer { class NullDiagnosticConsumer : public DiagnosticConsumer { public: void handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, StringRef Text, + DiagnosticKind Kind, + StringRef FormatString, + ArrayRef FormatArgs, const DiagnosticInfo &Info) override; }; diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h index e1f2177534c48..8b90dd2f01704 100644 --- a/include/swift/AST/DiagnosticEngine.h +++ b/include/swift/AST/DiagnosticEngine.h @@ -20,7 +20,7 @@ #include "swift/AST/TypeLoc.h" #include "swift/AST/DeclNameLoc.h" -#include "swift/Basic/DiagnosticConsumer.h" +#include "swift/AST/DiagnosticConsumer.h" namespace swift { class Decl; @@ -260,6 +260,23 @@ namespace swift { } }; + struct DiagnosticFormatOptions { + const std::string OpeningQuotationMark; + const std::string ClosingQuotationMark; + const std::string AKAFormatString; + + DiagnosticFormatOptions(std::string OpeningQuotationMark, + std::string ClosingQuotationMark, + std::string AKAFormatString) + : OpeningQuotationMark(OpeningQuotationMark), + ClosingQuotationMark(ClosingQuotationMark), + AKAFormatString(AKAFormatString) {} + + DiagnosticFormatOptions() + : OpeningQuotationMark("'"), ClosingQuotationMark("'"), + AKAFormatString("'%1$s' (aka '%2$s')") {} + }; + /// Diagnostic - This is a specific instance of a diagnostic along with all of /// the DiagnosticArguments that it requires. class Diagnostic { @@ -723,6 +740,13 @@ namespace swift { /// \returns true if diagnostic is marked with PointsToFirstBadToken /// option. bool isDiagnosticPointsToFirstBadToken(DiagID id) const; + + /// \brief Format the given diagnostic text and place the result in the given + /// buffer. + static void formatDiagnosticText( + llvm::raw_ostream &Out, StringRef InText, + ArrayRef FormatArgs, + DiagnosticFormatOptions FormatOpts = DiagnosticFormatOptions()); private: /// \brief Flush the active diagnostic. diff --git a/include/swift/Basic/DiagnosticOptions.h b/include/swift/Basic/DiagnosticOptions.h index 5f5cd78d30144..9079cb4e2253a 100644 --- a/include/swift/Basic/DiagnosticOptions.h +++ b/include/swift/Basic/DiagnosticOptions.h @@ -13,6 +13,8 @@ #ifndef SWIFT_BASIC_DIAGNOSTICOPTIONS_H #define SWIFT_BASIC_DIAGNOSTICOPTIONS_H +#include "llvm/ADT/Hashing.h" + namespace swift { /// Options for controlling diagnostics. diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index e9fcf8d3b7d89..c10d7e3bdecb6 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -18,10 +18,10 @@ #ifndef SWIFT_FRONTEND_H #define SWIFT_FRONTEND_H -#include "swift/Basic/DiagnosticConsumer.h" #include "swift/Basic/DiagnosticOptions.h" #include "swift/Basic/LangOptions.h" #include "swift/Basic/SourceManager.h" +#include "swift/AST/DiagnosticConsumer.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/IRGenOptions.h" #include "swift/AST/LinkLibrary.h" diff --git a/include/swift/Frontend/PrintingDiagnosticConsumer.h b/include/swift/Frontend/PrintingDiagnosticConsumer.h index 32bb1b653569c..8415ede3f02e9 100644 --- a/include/swift/Frontend/PrintingDiagnosticConsumer.h +++ b/include/swift/Frontend/PrintingDiagnosticConsumer.h @@ -19,7 +19,7 @@ #define SWIFT_PRINTINGDIAGNOSTICCONSUMER_H #include "swift/Basic/LLVM.h" -#include "swift/Basic/DiagnosticConsumer.h" +#include "swift/AST/DiagnosticConsumer.h" #include "llvm/Support/raw_ostream.h" @@ -35,7 +35,9 @@ class PrintingDiagnosticConsumer : public DiagnosticConsumer { Stream(stream) { } virtual void handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, StringRef Text, + DiagnosticKind Kind, + StringRef FormatString, + ArrayRef FormatArgs, const DiagnosticInfo &Info) override; void forceColors() { diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 8499a7dbddc20..5f44d27e59205 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -23,6 +23,7 @@ add_swift_library(swiftAST STATIC DeclContext.cpp DeclNameLoc.cpp DefaultArgumentKind.cpp + DiagnosticConsumer.cpp DiagnosticEngine.cpp DiagnosticList.cpp DocComment.cpp diff --git a/lib/Basic/DiagnosticConsumer.cpp b/lib/AST/DiagnosticConsumer.cpp similarity index 62% rename from lib/Basic/DiagnosticConsumer.cpp rename to lib/AST/DiagnosticConsumer.cpp index ab11fb3f36220..0681432149d80 100644 --- a/lib/Basic/DiagnosticConsumer.cpp +++ b/lib/AST/DiagnosticConsumer.cpp @@ -15,7 +15,8 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "swift-basic" -#include "swift/Basic/DiagnosticConsumer.h" +#include "swift/AST/DiagnosticConsumer.h" +#include "swift/AST/DiagnosticEngine.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -23,11 +24,14 @@ using namespace swift; DiagnosticConsumer::~DiagnosticConsumer() { } -void NullDiagnosticConsumer::handleDiagnostic(SourceManager &SM, - SourceLoc Loc, - DiagnosticKind Kind, - StringRef Text, - const DiagnosticInfo &Info) { - DEBUG(llvm::dbgs() << "NullDiagnosticConsumer received diagnostic: " - << Text << "\n"); +void NullDiagnosticConsumer::handleDiagnostic( + SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, + StringRef FormatString, ArrayRef FormatArgs, + const DiagnosticInfo &Info) { + DEBUG({ + llvm::dbgs() << "NullDiagnosticConsumer received diagnostic: "; + DiagnosticEngine::formatDiagnosticText(llvm::dbgs(), FormatString, + FormatArgs); + llvm::dbgs() << "\n"; + }); } diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index 277dc3a9e852f..f1ae63e0a2381 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -28,6 +28,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" using namespace swift; @@ -288,10 +289,6 @@ skipToDelimiter(StringRef &Text, char Delim, bool *FoundDelim = nullptr) { return Result; } -static void formatDiagnosticText(StringRef InText, - ArrayRef Args, - llvm::raw_ostream &Out); - /// Handle the integer 'select' modifier. This is used like this: /// %select{foo|bar|baz}2. This means that the integer argument "%2" has a /// value from 0-2. If the value is 0, the diagnostic prints 'foo'. @@ -300,6 +297,7 @@ static void formatDiagnosticText(StringRef InText, static void formatSelectionArgument(StringRef ModifierArguments, ArrayRef Args, unsigned SelectedIndex, + DiagnosticFormatOptions FormatOpts, llvm::raw_ostream &Out) { bool foundPipe = false; do { @@ -307,7 +305,7 @@ static void formatSelectionArgument(StringRef ModifierArguments, "Index beyond bounds in %select modifier"); StringRef Text = skipToDelimiter(ModifierArguments, '|', &foundPipe); if (SelectedIndex == 0) { - formatDiagnosticText(Text, Args, Out); + DiagnosticEngine::formatDiagnosticText(Out, Text, Args, FormatOpts); break; } --SelectedIndex; @@ -321,14 +319,15 @@ static void formatDiagnosticArgument(StringRef Modifier, StringRef ModifierArguments, ArrayRef Args, unsigned ArgIndex, + DiagnosticFormatOptions FormatOpts, llvm::raw_ostream &Out) { const DiagnosticArgument &Arg = Args[ArgIndex]; switch (Arg.getKind()) { case DiagnosticArgumentKind::Integer: if (Modifier == "select") { assert(Arg.getAsInteger() >= 0 && "Negative selection index"); - formatSelectionArgument(ModifierArguments, Args, Arg.getAsInteger(), - Out); + formatSelectionArgument(ModifierArguments, Args, Arg.getAsInteger(), + FormatOpts, Out); } else if (Modifier == "s") { if (Arg.getAsInteger() != 1) Out << 's'; @@ -340,8 +339,8 @@ static void formatDiagnosticArgument(StringRef Modifier, case DiagnosticArgumentKind::Unsigned: if (Modifier == "select") { - formatSelectionArgument(ModifierArguments, Args, Arg.getAsUnsigned(), - Out); + formatSelectionArgument(ModifierArguments, Args, Arg.getAsUnsigned(), + FormatOpts, Out); } else if (Modifier == "s") { if (Arg.getAsUnsigned() != 1) Out << 's'; @@ -358,14 +357,15 @@ static void formatDiagnosticArgument(StringRef Modifier, case DiagnosticArgumentKind::Identifier: assert(Modifier.empty() && "Improper modifier for identifier argument"); - Out << '\''; + Out << FormatOpts.OpeningQuotationMark; Arg.getAsIdentifier().printPretty(Out); - Out << '\''; + Out << FormatOpts.ClosingQuotationMark; break; case DiagnosticArgumentKind::ObjCSelector: assert(Modifier.empty() && "Improper modifier for selector argument"); - Out << '\'' << Arg.getAsObjCSelector() << '\''; + Out << FormatOpts.OpeningQuotationMark << Arg.getAsObjCSelector() + << FormatOpts.ClosingQuotationMark; break; case DiagnosticArgumentKind::ValueDecl: @@ -380,8 +380,6 @@ static void formatDiagnosticArgument(StringRef Modifier, // Strip extraneous parentheses; they add no value. auto type = Arg.getAsType()->getWithoutParens(); std::string typeName = type->getString(); - Out << '\'' << typeName << '\''; - // Decide whether to show the desugared type or not. We filter out some // cases to avoid too much noise. @@ -409,13 +407,22 @@ static void formatDiagnosticArgument(StringRef Modifier, if (showAKA && type->hasTypeParameter()) showAKA = false; - if (showAKA) - Out << " (aka '" << type->getCanonicalType() << "')"; + if (showAKA) { + llvm::SmallString<256> AkaText; + llvm::raw_svector_ostream OutAka(AkaText); + OutAka << type->getCanonicalType(); + Out << llvm::format(FormatOpts.AKAFormatString.c_str(), typeName.c_str(), + AkaText.c_str()); + } else { + Out << FormatOpts.OpeningQuotationMark << typeName + << FormatOpts.ClosingQuotationMark; + } break; } case DiagnosticArgumentKind::TypeRepr: assert(Modifier.empty() && "Improper modifier for TypeRepr argument"); - Out << '\'' << Arg.getAsTypeRepr() << '\''; + Out << FormatOpts.OpeningQuotationMark << Arg.getAsTypeRepr() + << FormatOpts.ClosingQuotationMark; break; case DiagnosticArgumentKind::PatternKind: assert(Modifier.empty() && "Improper modifier for PatternKind argument"); @@ -424,7 +431,8 @@ static void formatDiagnosticArgument(StringRef Modifier, case DiagnosticArgumentKind::StaticSpellingKind: if (Modifier == "select") { formatSelectionArgument(ModifierArguments, Args, - unsigned(Arg.getAsStaticSpellingKind()), Out); + unsigned(Arg.getAsStaticSpellingKind()), + FormatOpts, Out); } else { assert(Modifier.empty() && "Improper modifier for StaticSpellingKind argument"); @@ -442,7 +450,9 @@ static void formatDiagnosticArgument(StringRef Modifier, assert(Modifier.empty() && "Improper modifier for DeclAttribute argument"); if (Arg.getAsDeclAttribute()->isDeclModifier()) - Out << '\'' << Arg.getAsDeclAttribute()->getAttrName() << '\''; + Out << FormatOpts.OpeningQuotationMark + << Arg.getAsDeclAttribute()->getAttrName() + << FormatOpts.ClosingQuotationMark; else Out << '@' << Arg.getAsDeclAttribute()->getAttrName(); break; @@ -454,16 +464,17 @@ static void formatDiagnosticArgument(StringRef Modifier, break; case DiagnosticArgumentKind::LayoutConstraint: assert(Modifier.empty() && "Improper modifier for LayoutConstraint argument"); - Out << '\'' << Arg.getAsLayoutConstraint() << '\''; + Out << FormatOpts.OpeningQuotationMark << Arg.getAsLayoutConstraint() + << FormatOpts.ClosingQuotationMark; break; } } /// \brief Format the given diagnostic text and place the result in the given /// buffer. -static void formatDiagnosticText(StringRef InText, - ArrayRef Args, - llvm::raw_ostream &Out) { +void DiagnosticEngine::formatDiagnosticText( + llvm::raw_ostream &Out, StringRef InText, ArrayRef Args, + DiagnosticFormatOptions FormatOpts) { while (!InText.empty()) { size_t Percent = InText.find('%'); if (Percent == StringRef::npos) { @@ -515,7 +526,8 @@ static void formatDiagnosticText(StringRef InText, InText = InText.substr(Length); // Convert the argument to a string. - formatDiagnosticArgument(Modifier, ModifierArguments, Args, ArgIndex, Out); + formatDiagnosticArgument(Modifier, ModifierArguments, Args, ArgIndex, + FormatOpts, Out); } } @@ -736,21 +748,15 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) { } } - // Actually substitute the diagnostic arguments into the diagnostic text. - llvm::SmallString<256> Text; - { - llvm::raw_svector_ostream Out(Text); - formatDiagnosticText(diagnosticStrings[(unsigned)diagnostic.getID()], - diagnostic.getArgs(), Out); - } - // Pass the diagnostic off to the consumer. DiagnosticInfo Info; Info.ID = diagnostic.getID(); Info.Ranges = diagnostic.getRanges(); Info.FixIts = diagnostic.getFixIts(); for (auto &Consumer : Consumers) { - Consumer->handleDiagnostic(SourceMgr, loc, toDiagnosticKind(behavior), Text, + Consumer->handleDiagnostic(SourceMgr, loc, toDiagnosticKind(behavior), + diagnosticStrings[(unsigned)Info.ID], + diagnostic.getArgs(), Info); } } diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt index c007c7b23bfaf..5510318e5d550 100644 --- a/lib/Basic/CMakeLists.txt +++ b/lib/Basic/CMakeLists.txt @@ -67,7 +67,6 @@ set(version_inc_files add_swift_library(swiftBasic STATIC Cache.cpp ClusteredBitVector.cpp - DiagnosticConsumer.cpp DiverseStack.cpp Edit.cpp EditorPlaceholder.cpp diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp index 7a95c5584ade6..b77912040b5f6 100644 --- a/lib/Frontend/PrintingDiagnosticConsumer.cpp +++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp @@ -17,6 +17,8 @@ #include "swift/Frontend/PrintingDiagnosticConsumer.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/SourceManager.h" +#include "swift/AST/DiagnosticEngine.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/MemoryBuffer.h" @@ -65,11 +67,10 @@ llvm::SMLoc DiagnosticConsumer::getRawLoc(SourceLoc loc) { return loc.Value; } -void -PrintingDiagnosticConsumer::handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, - StringRef Text, - const DiagnosticInfo &Info) { +void PrintingDiagnosticConsumer::handleDiagnostic( + SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, + StringRef FormatString, ArrayRef FormatArgs, + const DiagnosticInfo &Info) { // Determine what kind of diagnostic we're emitting. llvm::SourceMgr::DiagKind SMKind; switch (Kind) { @@ -103,6 +104,14 @@ PrintingDiagnosticConsumer::handleDiagnostic(SourceManager &SM, SourceLoc Loc, ColoredStream coloredErrs{Stream}; raw_ostream &out = ForceColors ? coloredErrs : Stream; const llvm::SourceMgr &rawSM = SM.getLLVMSourceMgr(); + + // Actually substitute the diagnostic arguments into the diagnostic text. + llvm::SmallString<256> Text; + { + llvm::raw_svector_ostream Out(Text); + DiagnosticEngine::formatDiagnosticText(Out, FormatString, FormatArgs); + } + auto Msg = SM.GetMessage(Loc, SMKind, Text, Ranges, FixIts); rawSM.PrintMessage(out, Msg); } diff --git a/lib/Frontend/SerializedDiagnosticConsumer.cpp b/lib/Frontend/SerializedDiagnosticConsumer.cpp index fe00841f1579a..7bc3fa82e5431 100644 --- a/lib/Frontend/SerializedDiagnosticConsumer.cpp +++ b/lib/Frontend/SerializedDiagnosticConsumer.cpp @@ -15,7 +15,7 @@ //===----------------------------------------------------------------------===// #include "swift/Frontend/SerializedDiagnosticConsumer.h" -#include "swift/Basic/DiagnosticConsumer.h" +#include "swift/AST/DiagnosticConsumer.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/SourceManager.h" #include "swift/Parse/Lexer.h" @@ -149,7 +149,9 @@ class SerializedDiagnosticConsumer : public DiagnosticConsumer { } void handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, llvm::StringRef Text, + DiagnosticKind Kind, + StringRef FormatString, + ArrayRef FormatArgs, const DiagnosticInfo &Info) override; /// \brief The version of the diagnostics file. @@ -493,12 +495,11 @@ emitDiagnosticMessage(SourceManager &SM, } } -void -SerializedDiagnosticConsumer::handleDiagnostic(SourceManager &SM, - SourceLoc Loc, - DiagnosticKind Kind, - StringRef Text, - const DiagnosticInfo &Info) { +void SerializedDiagnosticConsumer::handleDiagnostic( + SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, + StringRef FormatString, ArrayRef FormatArgs, + const DiagnosticInfo &Info) { + // Enter the block for a non-note diagnostic immediately, rather // than waiting for beginDiagnostic, in case associated notes // are emitted before we get there. @@ -517,6 +518,13 @@ SerializedDiagnosticConsumer::handleDiagnostic(SourceManager &SM, if (bracketDiagnostic) enterDiagBlock(); + // Actually substitute the diagnostic arguments into the diagnostic text. + llvm::SmallString<256> Text; + { + llvm::raw_svector_ostream Out(Text); + DiagnosticEngine::formatDiagnosticText(Out, FormatString, FormatArgs); + } + emitDiagnosticMessage(SM, Loc, Kind, Text, Info); if (bracketDiagnostic) diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 2a51d508b0257..9238c50d60a37 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -224,7 +224,9 @@ class JSONFixitWriter : public DiagnosticConsumer { } private: void handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, StringRef Text, + DiagnosticKind Kind, + StringRef FormatString, + ArrayRef FormatArgs, const DiagnosticInfo &Info) override { if (!shouldFix(Kind, Info)) return; @@ -921,10 +923,10 @@ int swift::performFrontend(ArrayRef Args, PDC.handleDiagnostic(dummyMgr, SourceLoc(), DiagnosticKind::Error, "fatal error encountered during compilation; please " "file a bug report with your project and the crash " - "log", + "log", {}, DiagnosticInfo()); PDC.handleDiagnostic(dummyMgr, SourceLoc(), DiagnosticKind::Note, reason, - DiagnosticInfo()); + {}, DiagnosticInfo()); if (shouldCrash) abort(); }; diff --git a/lib/Sema/InstrumenterSupport.cpp b/lib/Sema/InstrumenterSupport.cpp index 76403f9ad06fc..3f269c9d16e9f 100644 --- a/lib/Sema/InstrumenterSupport.cpp +++ b/lib/Sema/InstrumenterSupport.cpp @@ -33,12 +33,16 @@ class ErrorGatherer : public DiagnosticConsumer { } ~ErrorGatherer() override { diags.takeConsumers(); } void handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, StringRef Text, + DiagnosticKind Kind, + StringRef FormatString, + ArrayRef FormatArgs, const DiagnosticInfo &Info) override { if (Kind == swift::DiagnosticKind::Error) { error = true; } - llvm::errs() << Text << "\n"; + DiagnosticEngine::formatDiagnosticText(llvm::errs(), FormatString, + FormatArgs); + llvm::errs() << "\n"; } bool hadError() { return error; } }; diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index 1729964f1d717..1d815624271cb 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -46,7 +46,9 @@ class StreamDiagConsumer : public DiagnosticConsumer { StreamDiagConsumer(llvm::raw_ostream &OS) : OS(OS) {} void handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, StringRef Text, + DiagnosticKind Kind, + StringRef FormatString, + ArrayRef FormatArgs, const DiagnosticInfo &Info) override { // FIXME: Print location info if available. switch (Kind) { @@ -54,7 +56,7 @@ class StreamDiagConsumer : public DiagnosticConsumer { case DiagnosticKind::Warning: OS << "warning: "; break; case DiagnosticKind::Note: OS << "note: "; break; } - OS << Text; + DiagnosticEngine::formatDiagnosticText(OS, FormatString, FormatArgs); } }; } // end anonymous namespace diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index 0b82f143a02b4..ca63d67b65d2a 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -43,9 +43,11 @@ using namespace SourceKit; using namespace swift; using namespace ide; -void EditorDiagConsumer::handleDiagnostic(SourceManager &SM, SourceLoc Loc, - DiagnosticKind Kind, StringRef Text, - const DiagnosticInfo &Info) { +void EditorDiagConsumer::handleDiagnostic( + SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, + StringRef FormatString, ArrayRef FormatArgs, + const DiagnosticInfo &Info) { + if (Kind == DiagnosticKind::Error) { HadAnyError = true; } @@ -68,7 +70,13 @@ void EditorDiagConsumer::handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticEntryInfo SKInfo; - SKInfo.Description = Text; + // Actually substitute the diagnostic arguments into the diagnostic text. + llvm::SmallString<256> Text; + { + llvm::raw_svector_ostream Out(Text); + DiagnosticEngine::formatDiagnosticText(Out, FormatString, FormatArgs); + } + SKInfo.Description = Text.str(); unsigned BufferID = SM.findBufferContainingLoc(Loc); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h b/tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h index cc9c5de97ba22..e611e0db4ffa7 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h @@ -14,7 +14,7 @@ #define LLVM_SOURCEKIT_LIB_SWIFTLANG_SWIFTEDITORDIAGCONSUMER_H #include "SourceKit/Core/LangSupport.h" -#include "swift/Basic/DiagnosticConsumer.h" +#include "swift/AST/DiagnosticConsumer.h" #include "llvm/ADT/DenseMap.h" namespace SourceKit { @@ -67,7 +67,9 @@ class EditorDiagConsumer : public swift::DiagnosticConsumer { bool hadAnyError() const { return HadAnyError; } void handleDiagnostic(swift::SourceManager &SM, swift::SourceLoc Loc, - swift::DiagnosticKind Kind, StringRef Text, + swift::DiagnosticKind Kind, + StringRef FormatString, + ArrayRef FormatArgs, const swift::DiagnosticInfo &Info) override; }; diff --git a/tools/driver/swift_format_main.cpp b/tools/driver/swift_format_main.cpp index c38640207827f..2873b2924895d 100644 --- a/tools/driver/swift_format_main.cpp +++ b/tools/driver/swift_format_main.cpp @@ -42,9 +42,13 @@ class FormatterDocument { std::unique_ptr Parser; class FormatterDiagConsumer : public swift::DiagnosticConsumer { void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, - StringRef Text, + StringRef FormatString, + ArrayRef FormatArgs, const swift::DiagnosticInfo &Info) override { - llvm::errs() << "Parse error: " << Text << "\n"; + llvm::errs() << "Parse error: "; + DiagnosticEngine::formatDiagnosticText(llvm::errs(), FormatString, + FormatArgs); + llvm::errs() << "\n"; } } DiagConsumer; diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 12559b345f0fa..fdc79d919c956 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -17,6 +17,7 @@ #include "swift/AST/ASTWalker.h" #include "swift/AST/Comment.h" #include "swift/AST/DebuggerClient.h" +#include "swift/AST/DiagnosticConsumer.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/ASTMangler.h" #include "swift/AST/PrintOptions.h" @@ -24,7 +25,6 @@ #include "swift/AST/SourceEntityWalker.h" #include "swift/AST/USRGeneration.h" #include "swift/Demangling/Demangle.h" -#include "swift/Basic/DiagnosticConsumer.h" #include "swift/Basic/LangOptions.h" #include "swift/Basic/PrimitiveParsing.h" #include "swift/Basic/LLVMInitialize.h"