[clangd] Don't use the optional "severity" when comparing Diagnostic.
authorHaojian Wu <hokein@google.com>
Tue, 19 Dec 2017 20:52:56 +0000 (20:52 +0000)
committerHaojian Wu <hokein@google.com>
Tue, 19 Dec 2017 20:52:56 +0000 (20:52 +0000)
Summary:
We use Diagnostic as a key to find the corresponding FixIt when we do
the "apply-fix", but the "severity" field could be omitted, in some cases,
the codeAction request sent from LSP clients (e.g. VScode) doesn't include the
`severity` field, which makes clangd fail to find the FixIt.

Test the following code in VScode, before the fix, no FixIt shown.

```
void main() {}
^~~~
```

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: klimek, ilya-biryukov, cfe-commits

Differential Revision: https://reviews.llvm.org/D41280

llvm-svn: 321106

clang-tools-extra/clangd/ClangdLSPServer.h
clang-tools-extra/clangd/Protocol.h

index ed05525..ca4b572 100644 (file)
@@ -88,7 +88,8 @@ private:
   bool IsDone = false;
 
   std::mutex FixItsMutex;
-  typedef std::map<clangd::Diagnostic, std::vector<TextEdit>>
+  typedef std::map<clangd::Diagnostic, std::vector<TextEdit>,
+                   LSPDiagnosticCompare>
       DiagnosticToReplacementMap;
   /// Caches FixIts per file and diagnostics
   llvm::StringMap<DiagnosticToReplacementMap> FixItsMap;
index 098df13..f2ad0db 100644 (file)
@@ -322,14 +322,15 @@ struct Diagnostic {
 
   /// The diagnostic's message.
   std::string message;
-
-  friend bool operator==(const Diagnostic &LHS, const Diagnostic &RHS) {
-    return std::tie(LHS.range, LHS.severity, LHS.message) ==
-           std::tie(RHS.range, RHS.severity, RHS.message);
-  }
-  friend bool operator<(const Diagnostic &LHS, const Diagnostic &RHS) {
-    return std::tie(LHS.range, LHS.severity, LHS.message) <
-           std::tie(RHS.range, RHS.severity, RHS.message);
+};
+/// A LSP-specific comparator used to find diagnostic in a container like
+/// std:map.
+/// We only use the required fields of Diagnostic to do the comparsion to avoid
+/// any regression issues from LSP clients (e.g. VScode), see
+/// https://git.io/vbr29
+struct LSPDiagnosticCompare {
+  bool operator()(const Diagnostic& LHS, const Diagnostic& RHS) const {
+    return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
   }
 };
 bool fromJSON(const json::Expr &, Diagnostic &);