diff options
Diffstat (limited to 'lib/Driver/TextDiagnosticPrinter.cpp')
-rw-r--r-- | lib/Driver/TextDiagnosticPrinter.cpp | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/lib/Driver/TextDiagnosticPrinter.cpp b/lib/Driver/TextDiagnosticPrinter.cpp index b5226f5131..8a7e40f13e 100644 --- a/lib/Driver/TextDiagnosticPrinter.cpp +++ b/lib/Driver/TextDiagnosticPrinter.cpp @@ -16,6 +16,7 @@ #include "clang/Lex/Lexer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallString.h" +#include <algorithm> using namespace clang; void TextDiagnosticPrinter:: @@ -104,7 +105,9 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, SourceRange *Ranges, unsigned NumRanges, - SourceManager &SM) { + SourceManager &SM, + const CodeModificationHint *Hints, + unsigned NumHints) { assert(!Loc.isInvalid() && "must have a valid source location here"); // We always emit diagnostics about the instantiation points, not the spelling @@ -205,6 +208,36 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, // Emit what we have computed. OS << SourceLine << '\n'; OS << CaretLine << '\n'; + + if (NumHints) { + std::string InsertionLine; + for (const CodeModificationHint *Hint = Hints, + *LastHint = Hints + NumHints; + Hint != LastHint; ++Hint) { + if (Hint->InsertionLoc.isValid()) { + // We have an insertion hint. Determine whether the inserted + // code is on the same line as the caret. + std::pair<FileID, unsigned> HintLocInfo + = SM.getDecomposedLoc(Hint->InsertionLoc); + if (SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) == + SM.getLineNumber(FID, FileOffset)) { + // Insert the new code into the line just below the code + // that the user wrote. + unsigned HintColNo + = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second); + unsigned LastColumnModified + = HintColNo - 1 + Hint->CodeToInsert.size(); + if (LastColumnModified > InsertionLine.size()) + InsertionLine.resize(LastColumnModified, ' '); + std::copy(Hint->CodeToInsert.begin(), Hint->CodeToInsert.end(), + InsertionLine.begin() + HintColNo - 1); + } + } + } + + if (!InsertionLine.empty()) + OS << InsertionLine << '\n'; + } } @@ -252,18 +285,30 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, // diagnostic, or if the diagnostic has ranges. We don't want to emit the // same caret multiple times if one loc has multiple diagnostics. if (CaretDiagnostics && Info.getLocation().isValid() && - ((LastLoc != Info.getLocation()) || Info.getNumRanges())) { + ((LastLoc != Info.getLocation()) || Info.getNumRanges() || + Info.getNumCodeModificationHints())) { // Cache the LastLoc, it allows us to omit duplicate source/caret spewage. LastLoc = Info.getLocation(); // Get the ranges into a local array we can hack on. - SourceRange Ranges[10]; + SourceRange Ranges[20]; unsigned NumRanges = Info.getNumRanges(); - assert(NumRanges < 10 && "Out of space"); + assert(NumRanges < 20 && "Out of space"); for (unsigned i = 0; i != NumRanges; ++i) Ranges[i] = Info.getRange(i); - EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager()); + unsigned NumHints = Info.getNumCodeModificationHints(); + for (unsigned idx = 0; idx < NumHints; ++idx) { + const CodeModificationHint &Hint = Info.getCodeModificationHint(idx); + if (Hint.RemoveRange.isValid()) { + assert(NumRanges < 20 && "Out of space"); + Ranges[NumRanges++] = Hint.RemoveRange; + } + } + + EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(), + Info.getCodeModificationHints(), + Info.getNumCodeModificationHints()); } OS.flush(); |