From 94f55784145e7e3f1414b5368d715fa43ca3b273 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 17 Feb 2009 07:38:37 +0000 Subject: [PATCH] split caret diagnostic printing out into its own function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64751 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/TextDiagnosticPrinter.h | 2 + lib/Driver/TextDiagnosticPrinter.cpp | 124 ++++++++++--------- 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/include/clang/Driver/TextDiagnosticPrinter.h b/include/clang/Driver/TextDiagnosticPrinter.h index 972fe6d8bc..49f456ff17 100644 --- a/include/clang/Driver/TextDiagnosticPrinter.h +++ b/include/clang/Driver/TextDiagnosticPrinter.h @@ -46,6 +46,8 @@ public: std::string &CaretLine, const std::string &SourceLine); + void EmitCaretDiagnostic(FullSourceLoc Loc, const DiagnosticInfo &Info); + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info); }; diff --git a/lib/Driver/TextDiagnosticPrinter.cpp b/lib/Driver/TextDiagnosticPrinter.cpp index 1d61f85c33..fae39ef5fe 100644 --- a/lib/Driver/TextDiagnosticPrinter.cpp +++ b/lib/Driver/TextDiagnosticPrinter.cpp @@ -101,6 +101,70 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, CaretLine[i] = '~'; } +void TextDiagnosticPrinter::EmitCaretDiagnostic(FullSourceLoc ILoc, + const DiagnosticInfo &Info) { + unsigned ColNo = ILoc.getInstantiationColumnNumber(); + + // Rewind from the current position to the start of the line. + const char *TokInstantiationPtr = ILoc.getCharacterData(); + const char *LineStart = TokInstantiationPtr-ColNo+1; // Column # is 1-based. + + // Compute the line end. Scan forward from the error position to the end of + // the line. + const char *BufEnd = ILoc.getBufferData().second; + const char *LineEnd = TokInstantiationPtr; + while (LineEnd != BufEnd && + *LineEnd != '\n' && *LineEnd != '\r') + ++LineEnd; + + // Copy the line of code into an std::string for ease of manipulation. + std::string SourceLine(LineStart, LineEnd); + + // Create a line for the caret that is filled with spaces that is the same + // length as the line of source code. + std::string CaretLine(LineEnd-LineStart, ' '); + + // Highlight all of the characters covered by Ranges with ~ characters. + for (unsigned i = 0; i != Info.getNumRanges(); ++i) + HighlightRange(Info.getRange(i), ILoc.getManager(), + ILoc.getInstantiationLineNumber(), + ILoc.getFileID(), CaretLine, SourceLine); + + // Next, insert the caret itself. + if (ColNo-1 < CaretLine.size()) + CaretLine[ColNo-1] = '^'; + else + CaretLine.push_back('^'); + + // Scan the source line, looking for tabs. If we find any, manually expand + // them to 8 characters and update the CaretLine to match. + for (unsigned i = 0; i != SourceLine.size(); ++i) { + if (SourceLine[i] != '\t') continue; + + // Replace this tab with at least one space. + SourceLine[i] = ' '; + + // Compute the number of spaces we need to insert. + unsigned NumSpaces = ((i+8)&~7) - (i+1); + assert(NumSpaces < 8 && "Invalid computation of space amt"); + + // Insert spaces into the SourceLine. + SourceLine.insert(i+1, NumSpaces, ' '); + + // Insert spaces or ~'s into CaretLine. + CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' '); + } + + // Finally, remove any blank spaces from the end of CaretLine. + while (CaretLine[CaretLine.size()-1] == ' ') + CaretLine.erase(CaretLine.end()-1); + + // Emit what we have computed. + OS << SourceLine << '\n'; + OS << CaretLine << '\n'; +} + + void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info) { // If the location is specified, print out a file/line/col and include trace @@ -152,66 +216,8 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, // Inspect the actual instantiation point of the diagnostic, we don't care // about presumed locations anymore. FullSourceLoc ILoc = Info.getLocation().getInstantiationLoc(); - - unsigned ColNo = ILoc.getInstantiationColumnNumber(); - - // Rewind from the current position to the start of the line. - const char *TokInstantiationPtr = ILoc.getCharacterData(); - const char *LineStart = TokInstantiationPtr-ColNo+1; // Column # is 1-based. - - // Compute the line end. Scan forward from the error position to the end of - // the line. - const char *BufEnd = ILoc.getBufferData().second; - const char *LineEnd = TokInstantiationPtr; - while (LineEnd != BufEnd && - *LineEnd != '\n' && *LineEnd != '\r') - ++LineEnd; - - // Copy the line of code into an std::string for ease of manipulation. - std::string SourceLine(LineStart, LineEnd); - - // Create a line for the caret that is filled with spaces that is the same - // length as the line of source code. - std::string CaretLine(LineEnd-LineStart, ' '); - - // Highlight all of the characters covered by Ranges with ~ characters. - for (unsigned i = 0; i != Info.getNumRanges(); ++i) - HighlightRange(Info.getRange(i), ILoc.getManager(), - ILoc.getInstantiationLineNumber(), - ILoc.getFileID(), CaretLine, SourceLine); - - // Next, insert the caret itself. - if (ColNo-1 < CaretLine.size()) - CaretLine[ColNo-1] = '^'; - else - CaretLine.push_back('^'); - - // Scan the source line, looking for tabs. If we find any, manually expand - // them to 8 characters and update the CaretLine to match. - for (unsigned i = 0; i != SourceLine.size(); ++i) { - if (SourceLine[i] != '\t') continue; - - // Replace this tab with at least one space. - SourceLine[i] = ' '; - - // Compute the number of spaces we need to insert. - unsigned NumSpaces = ((i+8)&~7) - (i+1); - assert(NumSpaces < 8 && "Invalid computation of space amt"); - - // Insert spaces into the SourceLine. - SourceLine.insert(i+1, NumSpaces, ' '); - - // Insert spaces or ~'s into CaretLine. - CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' '); - } - - // Finally, remove any blank spaces from the end of CaretLine. - while (CaretLine[CaretLine.size()-1] == ' ') - CaretLine.erase(CaretLine.end()-1); - // Emit what we have computed. - OS << SourceLine << '\n'; - OS << CaretLine << '\n'; + EmitCaretDiagnostic(ILoc, Info); } OS.flush(); -- 2.40.0