From: Chandler Carruth Date: Wed, 7 Sep 2011 07:02:31 +0000 (+0000) Subject: Move the HilightRange method from TextDiagnosticPrinter down to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6c57ccec994f09d732a381bb4bb16c79d181e5ac;p=clang Move the HilightRange method from TextDiagnosticPrinter down to CaretDiagnostic. It's completely generic, with nothing to do with the diagnostic client or info APIs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139227 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index ea9994ad06..9f6f10029c 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -56,12 +56,6 @@ public: void PrintIncludeStack(Diagnostic::Level Level, SourceLocation Loc, const SourceManager &SM); - void HighlightRange(const CharSourceRange &R, - const SourceManager &SrcMgr, - unsigned LineNo, FileID FID, - std::string &CaretLine, - const std::string &SourceLine); - virtual void HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info); diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 716ce06f77..9fa23f8492 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -101,86 +101,6 @@ void TextDiagnosticPrinter::PrintIncludeStack(Diagnostic::Level Level, PrintIncludeStackRecursively(OS, SM, Loc, DiagOpts->ShowLocation); } -/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s) -/// any characters in LineNo that intersect the SourceRange. -void TextDiagnosticPrinter::HighlightRange(const CharSourceRange &R, - const SourceManager &SM, - unsigned LineNo, FileID FID, - std::string &CaretLine, - const std::string &SourceLine) { - assert(CaretLine.size() == SourceLine.size() && - "Expect a correspondence between source and caret line!"); - if (!R.isValid()) return; - - SourceLocation Begin = SM.getExpansionLoc(R.getBegin()); - SourceLocation End = SM.getExpansionLoc(R.getEnd()); - - // If the End location and the start location are the same and are a macro - // location, then the range was something that came from a macro expansion - // or _Pragma. If this is an object-like macro, the best we can do is to - // highlight the range. If this is a function-like macro, we'd also like to - // highlight the arguments. - if (Begin == End && R.getEnd().isMacroID()) - End = SM.getExpansionRange(R.getEnd()).second; - - unsigned StartLineNo = SM.getExpansionLineNumber(Begin); - if (StartLineNo > LineNo || SM.getFileID(Begin) != FID) - return; // No intersection. - - unsigned EndLineNo = SM.getExpansionLineNumber(End); - if (EndLineNo < LineNo || SM.getFileID(End) != FID) - return; // No intersection. - - // Compute the column number of the start. - unsigned StartColNo = 0; - if (StartLineNo == LineNo) { - StartColNo = SM.getExpansionColumnNumber(Begin); - if (StartColNo) --StartColNo; // Zero base the col #. - } - - // Compute the column number of the end. - unsigned EndColNo = CaretLine.size(); - if (EndLineNo == LineNo) { - EndColNo = SM.getExpansionColumnNumber(End); - if (EndColNo) { - --EndColNo; // Zero base the col #. - - // Add in the length of the token, so that we cover multi-char tokens if - // this is a token range. - if (R.isTokenRange()) - EndColNo += Lexer::MeasureTokenLength(End, SM, *LangOpts); - } else { - EndColNo = CaretLine.size(); - } - } - - assert(StartColNo <= EndColNo && "Invalid range!"); - - // Check that a token range does not highlight only whitespace. - if (R.isTokenRange()) { - // Pick the first non-whitespace column. - while (StartColNo < SourceLine.size() && - (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t')) - ++StartColNo; - - // Pick the last non-whitespace column. - if (EndColNo > SourceLine.size()) - EndColNo = SourceLine.size(); - while (EndColNo-1 && - (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t')) - --EndColNo; - - // If the start/end passed each other, then we are trying to highlight a - // range that just exists in whitespace, which must be some sort of other - // bug. - assert(StartColNo <= EndColNo && "Trying to highlight whitespace??"); - } - - // Fill the range with ~'s. - for (unsigned i = StartColNo; i < EndColNo; ++i) - CaretLine[i] = '~'; -} - /// \brief When the source code line we want to print is too long for /// the terminal, select the "interesting" region. static void SelectInterestingSourceRegion(std::string &SourceLine, @@ -537,7 +457,7 @@ public: for (SmallVectorImpl::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) - Printer.HighlightRange(*I, SM, LineNo, FID, CaretLine, SourceLine); + HighlightRange(*I, LineNo, FID, SourceLine, CaretLine); // Next, insert the caret itself. if (ColNo-1 < CaretLine.size()) @@ -595,6 +515,84 @@ public: } private: + /// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo. + void HighlightRange(const CharSourceRange &R, + unsigned LineNo, FileID FID, + const std::string &SourceLine, + std::string &CaretLine) { + assert(CaretLine.size() == SourceLine.size() && + "Expect a correspondence between source and caret line!"); + if (!R.isValid()) return; + + SourceLocation Begin = SM.getExpansionLoc(R.getBegin()); + SourceLocation End = SM.getExpansionLoc(R.getEnd()); + + // If the End location and the start location are the same and are a macro + // location, then the range was something that came from a macro expansion + // or _Pragma. If this is an object-like macro, the best we can do is to + // highlight the range. If this is a function-like macro, we'd also like to + // highlight the arguments. + if (Begin == End && R.getEnd().isMacroID()) + End = SM.getExpansionRange(R.getEnd()).second; + + unsigned StartLineNo = SM.getExpansionLineNumber(Begin); + if (StartLineNo > LineNo || SM.getFileID(Begin) != FID) + return; // No intersection. + + unsigned EndLineNo = SM.getExpansionLineNumber(End); + if (EndLineNo < LineNo || SM.getFileID(End) != FID) + return; // No intersection. + + // Compute the column number of the start. + unsigned StartColNo = 0; + if (StartLineNo == LineNo) { + StartColNo = SM.getExpansionColumnNumber(Begin); + if (StartColNo) --StartColNo; // Zero base the col #. + } + + // Compute the column number of the end. + unsigned EndColNo = CaretLine.size(); + if (EndLineNo == LineNo) { + EndColNo = SM.getExpansionColumnNumber(End); + if (EndColNo) { + --EndColNo; // Zero base the col #. + + // Add in the length of the token, so that we cover multi-char tokens if + // this is a token range. + if (R.isTokenRange()) + EndColNo += Lexer::MeasureTokenLength(End, SM, LangOpts); + } else { + EndColNo = CaretLine.size(); + } + } + + assert(StartColNo <= EndColNo && "Invalid range!"); + + // Check that a token range does not highlight only whitespace. + if (R.isTokenRange()) { + // Pick the first non-whitespace column. + while (StartColNo < SourceLine.size() && + (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t')) + ++StartColNo; + + // Pick the last non-whitespace column. + if (EndColNo > SourceLine.size()) + EndColNo = SourceLine.size(); + while (EndColNo-1 && + (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t')) + --EndColNo; + + // If the start/end passed each other, then we are trying to highlight a + // range that just exists in whitespace, which must be some sort of other + // bug. + assert(StartColNo <= EndColNo && "Trying to highlight whitespace??"); + } + + // Fill the range with ~'s. + for (unsigned i = StartColNo; i < EndColNo; ++i) + CaretLine[i] = '~'; + } + std::string BuildFixItInsertionLine(unsigned LineNo, const char *LineStart, const char *LineEnd,