Consistently handle clang-tidy check names in ClangTidyError.

Summary:
This patch removes " [check-name]" from the end of
ClangTidyMessage::Message. The " [check-name]" part is only appended when
printing diagnostics on the console. Clang errors are now marked with
"clang-diagnostic-error" check name, remarks and unknown warnings are marked
with "clang-diagnostic-unknown".

Reviewers: djasper

Reviewed By: djasper

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D4356

llvm-svn: 212180
This commit is contained in:
Alexander Kornienko 2014-07-02 15:05:04 +00:00
parent fd0346880e
commit 742790cd9f
3 changed files with 56 additions and 29 deletions
clang-tools-extra

View File

@ -104,31 +104,28 @@ public:
DiagPrinter->BeginSourceFile(LangOpts);
}
void reportDiagnostic(const ClangTidyMessage &Message,
DiagnosticsEngine::Level Level,
const tooling::Replacements *Fixes = nullptr) {
void reportDiagnostic(const ClangTidyError &Error) {
const ClangTidyMessage &Message = Error.Message;
SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
// Contains a pair for each attempted fix: location and whether the fix was
// applied successfully.
SmallVector<std::pair<SourceLocation, bool>, 4> FixLocations;
{
auto Level = static_cast<DiagnosticsEngine::Level>(Error.DiagLevel);
DiagnosticBuilder Diag =
Diags.Report(Loc, Diags.getCustomDiagID(Level, "%0"))
<< Message.Message;
if (Fixes != nullptr) {
for (const tooling::Replacement &Fix : *Fixes) {
SourceLocation FixLoc =
getLocation(Fix.getFilePath(), Fix.getOffset());
SourceLocation FixEndLoc = FixLoc.getLocWithOffset(Fix.getLength());
Diag << FixItHint::CreateReplacement(SourceRange(FixLoc, FixEndLoc),
Fix.getReplacementText());
++TotalFixes;
if (ApplyFixes) {
bool Success = Fix.isApplicable() && Fix.apply(Rewrite);
if (Success)
++AppliedFixes;
FixLocations.push_back(std::make_pair(FixLoc, Success));
}
Diags.Report(Loc, Diags.getCustomDiagID(Level, "%0 [%1]"))
<< Message.Message << Error.CheckName;
for (const tooling::Replacement &Fix : Error.Fix) {
SourceLocation FixLoc = getLocation(Fix.getFilePath(), Fix.getOffset());
SourceLocation FixEndLoc = FixLoc.getLocWithOffset(Fix.getLength());
Diag << FixItHint::CreateReplacement(SourceRange(FixLoc, FixEndLoc),
Fix.getReplacementText());
++TotalFixes;
if (ApplyFixes) {
bool Success = Fix.isApplicable() && Fix.apply(Rewrite);
if (Success)
++AppliedFixes;
FixLocations.push_back(std::make_pair(FixLoc, Success));
}
}
}
@ -136,6 +133,8 @@ public:
Diags.Report(Fix.first, Fix.second ? diag::note_fixit_applied
: diag::note_fixit_failed);
}
for (const ClangTidyMessage &Note : Error.Notes)
reportNote(Note);
}
void Finish() {
@ -157,6 +156,13 @@ private:
return SourceMgr.getLocForStartOfFile(ID).getLocWithOffset(Offset);
}
void reportNote(const ClangTidyMessage &Message) {
SourceLocation Loc = getLocation(Message.FilePath, Message.FileOffset);
DiagnosticBuilder Diag =
Diags.Report(Loc, Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0"))
<< Message.Message;
}
FileManager Files;
LangOptions LangOpts; // FIXME: use langopts from each original file
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
@ -349,13 +355,8 @@ ClangTidyStats runClangTidy(ClangTidyOptionsProvider *OptionsProvider,
void handleErrors(const std::vector<ClangTidyError> &Errors, bool Fix) {
ErrorReporter Reporter(Fix);
for (const ClangTidyError &Error : Errors) {
Reporter.reportDiagnostic(
Error.Message, static_cast<DiagnosticsEngine::Level>(Error.DiagLevel),
&Error.Fix);
for (const ClangTidyMessage &Note : Error.Notes)
Reporter.reportDiagnostic(Note, DiagnosticsEngine::Note);
}
for (const ClangTidyError &Error : Errors)
Reporter.reportDiagnostic(Error);
Reporter.Finish();
}

View File

@ -40,6 +40,14 @@ protected:
ArrayRef<CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag Info) override {
// Remove check name from the message.
// FIXME: Remove this once there's a better way to pass check names than
// appending the check name to the message in ClangTidyContext::diag and
// using getCustomDiagID.
std::string CheckNameInMessage = " [" + Error.CheckName + "]";
if (Message.endswith(CheckNameInMessage))
Message = Message.substr(0, Message.size() - CheckNameInMessage.size());
ClangTidyMessage TidyMessage = Loc.isValid()
? ClangTidyMessage(Message, *SM, Loc)
: ClangTidyMessage(Message);
@ -259,7 +267,6 @@ void ClangTidyDiagnosticConsumer::HandleDiagnostic(
assert(!Errors.empty() &&
"A diagnostic note can only be appended to a message.");
} else {
// FIXME: Pass all errors here regardless of filters and non-user code.
finalizeLastError();
StringRef WarningOption =
Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(
@ -268,9 +275,28 @@ void ClangTidyDiagnosticConsumer::HandleDiagnostic(
? ("clang-diagnostic-" + WarningOption).str()
: Context.getCheckName(Info.getID()).str();
if (CheckName.empty()) {
// This is a compiler diagnostic without a warning option. Assign check
// name based on its level.
switch (DiagLevel) {
case DiagnosticsEngine::Error:
case DiagnosticsEngine::Fatal:
CheckName = "clang-diagnostic-error";
break;
case DiagnosticsEngine::Warning:
CheckName = "clang-diagnostic-warning";
break;
default:
CheckName = "clang-diagnostic-unknown";
break;
}
}
ClangTidyError::Level Level = ClangTidyError::Warning;
if (DiagLevel == DiagnosticsEngine::Error ||
DiagLevel == DiagnosticsEngine::Fatal) {
// Force reporting of Clang errors regardless of filters and non-user
// code.
Level = ClangTidyError::Error;
LastErrorRelatesToUserCode = true;
LastErrorPassesLineFilter = true;

View File

@ -7,8 +7,8 @@
// CHECK2-NOT: warning
// CHECK3-NOT: warning
// CHECK1: error: error reading '{{.*}}.nonexistent.cpp'
// CHECK2: error: unknown argument: '-fan-unknown-option'
// CHECK1: error: error reading '{{.*}}.nonexistent.cpp' [clang-diagnostic-error]
// CHECK2: error: unknown argument: '-fan-unknown-option' [clang-diagnostic-error]
// CHECK2: :[[@LINE+2]]:9: warning: implicit conversion from 'double' to 'int' changes value
// CHECK3: :[[@LINE+1]]:9: warning: implicit conversion from 'double' to 'int' changes value