summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/Diagnostics.cpp
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2018-04-03 17:35:57 +0000
committerSam McCall <sam.mccall@gmail.com>2018-04-03 17:35:57 +0000
commitba3c02e461f3df902a3f3b180ae23860af50fafc (patch)
tree1ffa3a19a866a84683d6d9494054776e668fa381 /clang-tools-extra/clangd/Diagnostics.cpp
parentf7226ed67d2212d72af99f600c7df882d4b1f826 (diff)
downloadbcm5719-llvm-ba3c02e461f3df902a3f3b180ae23860af50fafc.tar.gz
bcm5719-llvm-ba3c02e461f3df902a3f3b180ae23860af50fafc.zip
[clangd] synthesize fix message when the diagnostic doesn't provide one.
Summary: Currently if a fix is attached directly to a diagnostic, we repeat the diagnostic message as the fix message. From eyeballing the top diagnostics, it seems describing the textual replacement would be much clearer. e.g. error: use of undeclared identifier 'goo'; did you mean 'foo'? action before: use of undeclared identifier 'goo'; did you mean 'foo'? action after: change 'goo' to 'foo' Reviewers: ilya-biryukov Subscribers: klimek, jkorous-apple, ioeric, MaskRay, cfe-commits Differential Revision: https://reviews.llvm.org/D45069 llvm-svn: 329090
Diffstat (limited to 'clang-tools-extra/clangd/Diagnostics.cpp')
-rw-r--r--clang-tools-extra/clangd/Diagnostics.cpp28
1 files changed, 24 insertions, 4 deletions
diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp
index e497823ed0e..a52891bb628 100644
--- a/clang-tools-extra/clangd/Diagnostics.cpp
+++ b/clang-tools-extra/clangd/Diagnostics.cpp
@@ -297,7 +297,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
return D;
};
- auto AddFix = [&]() -> bool {
+ auto AddFix = [&](bool SyntheticMessage) -> bool {
assert(!Info.getFixItHints().empty() &&
"diagnostic does not have attached fix-its");
if (!InsideMainFile)
@@ -312,7 +312,27 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
}
llvm::SmallString<64> Message;
- Info.FormatDiagnostic(Message);
+ // If requested and possible, create a message like "change 'foo' to 'bar'".
+ if (SyntheticMessage && Info.getNumFixItHints() == 1) {
+ const auto &FixIt = Info.getFixItHint(0);
+ bool Invalid = false;
+ StringRef Remove = Lexer::getSourceText(
+ FixIt.RemoveRange, Info.getSourceManager(), *LangOpts, &Invalid);
+ StringRef Insert = FixIt.CodeToInsert;
+ if (!Invalid) {
+ llvm::raw_svector_ostream M(Message);
+ if (!Remove.empty() && !Insert.empty())
+ M << "change '" << Remove << "' to '" << Insert << "'";
+ else if (!Remove.empty())
+ M << "remove '" << Remove << "'";
+ else if (!Insert.empty())
+ M << "insert '" << Insert << "'";
+ // Don't allow source code to inject newlines into diagnostics.
+ std::replace(Message.begin(), Message.end(), '\n', ' ');
+ }
+ }
+ if (Message.empty()) // either !SytheticMessage, or we failed to make one.
+ Info.FormatDiagnostic(Message);
LastDiag->Fixes.push_back(Fix{Message.str(), std::move(Edits)});
return true;
};
@@ -325,7 +345,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
FillDiagBase(*LastDiag);
if (!Info.getFixItHints().empty())
- AddFix();
+ AddFix(true /* try to invent a message instead of repeating the diag */);
} else {
// Handle a note to an existing diagnostic.
if (!LastDiag) {
@@ -337,7 +357,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
if (!Info.getFixItHints().empty()) {
// A clang note with fix-it is not a separate diagnostic in clangd. We
// attach it as a Fix to the main diagnostic instead.
- if (!AddFix())
+ if (!AddFix(false /* use the note as the message */))
IgnoreDiagnostics::log(DiagLevel, Info);
} else {
// A clang note without fix-its corresponds to clangd::Note.
OpenPOWER on IntegriCloud