[clang-tools-extra] r313536 - [clangd] Fix codeAction not decoded properly when sent from some clients

Marc-Andre Laperle via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 18 08:02:59 PDT 2017


Author: malaperle
Date: Mon Sep 18 08:02:59 2017
New Revision: 313536

URL: http://llvm.org/viewvc/llvm-project?rev=313536&view=rev
Log:
[clangd] Fix codeAction not decoded properly when sent from some clients

Summary:
Fix for bug https://bugs.llvm.org/show_bug.cgi?id=34559
Also log unknown fields instead of aborting the JSON parsing because it's
common that new optional fields are added either in new versions of the protocol
or extensions.

Reviewers: ilya-biryukov

Reviewed By: ilya-biryukov

Subscribers: ilya-biryukov

Tags: #clang-tools-extra

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

Modified:
    clang-tools-extra/trunk/clangd/Protocol.cpp
    clang-tools-extra/trunk/clangd/Protocol.h
    clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
    clang-tools-extra/trunk/test/clangd/fixits.test

Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=313536&r1=313535&r2=313536&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
+++ clang-tools-extra/trunk/clangd/Protocol.cpp Mon Sep 18 08:02:59 2017
@@ -13,13 +13,22 @@
 //===----------------------------------------------------------------------===//
 
 #include "Protocol.h"
+#include "JSONRPCDispatcher.h"
+
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang::clangd;
 
+namespace {
+void logIgnoredField(llvm::StringRef KeyValue, JSONOutput &Output) {
+  Output.log(llvm::formatv("Ignored unknown field \"{0}\"\n", KeyValue));
+}
+} // namespace
+
 URI URI::fromUri(llvm::StringRef uri) {
   URI Result;
   Result.uri = uri;
@@ -55,7 +64,8 @@ URI URI::parse(llvm::yaml::ScalarNode *P
 std::string URI::unparse(const URI &U) { return "\"" + U.uri + "\""; }
 
 llvm::Optional<TextDocumentIdentifier>
-TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params) {
+TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params,
+                              JSONOutput &Output) {
   TextDocumentIdentifier Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -74,13 +84,14 @@ TextDocumentIdentifier::parse(llvm::yaml
     } else if (KeyValue == "version") {
       // FIXME: parse version, but only for VersionedTextDocumentIdentifiers.
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
-llvm::Optional<Position> Position::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<Position> Position::parse(llvm::yaml::MappingNode *Params,
+                                         JSONOutput &Output) {
   Position Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -106,7 +117,7 @@ llvm::Optional<Position> Position::parse
         return llvm::None;
       Result.character = Val;
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
@@ -119,7 +130,8 @@ std::string Position::unparse(const Posi
   return Result;
 }
 
-llvm::Optional<Range> Range::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<Range> Range::parse(llvm::yaml::MappingNode *Params,
+                                   JSONOutput &Output) {
   Range Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -135,17 +147,17 @@ llvm::Optional<Range> Range::parse(llvm:
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "start") {
-      auto Parsed = Position::parse(Value);
+      auto Parsed = Position::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.start = std::move(*Parsed);
     } else if (KeyValue == "end") {
-      auto Parsed = Position::parse(Value);
+      auto Parsed = Position::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.end = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
@@ -168,7 +180,7 @@ std::string Location::unparse(const Loca
 }
 
 llvm::Optional<TextDocumentItem>
-TextDocumentItem::parse(llvm::yaml::MappingNode *Params) {
+TextDocumentItem::parse(llvm::yaml::MappingNode *Params, JSONOutput &Output) {
   TextDocumentItem Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -195,13 +207,14 @@ TextDocumentItem::parse(llvm::yaml::Mapp
     } else if (KeyValue == "text") {
       Result.text = Value->getValue(Storage);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
-llvm::Optional<Metadata> Metadata::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<Metadata> Metadata::parse(llvm::yaml::MappingNode *Params,
+                                         JSONOutput &Output) {
   Metadata Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -223,12 +236,15 @@ llvm::Optional<Metadata> Metadata::parse
           return llvm::None;
         Result.extraFlags.push_back(Node->getValue(Storage));
       }
+    } else {
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
-llvm::Optional<TextEdit> TextEdit::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<TextEdit> TextEdit::parse(llvm::yaml::MappingNode *Params,
+                                         JSONOutput &Output) {
   TextEdit Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -244,7 +260,7 @@ llvm::Optional<TextEdit> TextEdit::parse
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = Range::parse(Map);
+      auto Parsed = Range::parse(Map, Output);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
@@ -254,7 +270,7 @@ llvm::Optional<TextEdit> TextEdit::parse
         return llvm::None;
       Result.newText = Node->getValue(Storage);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
@@ -269,7 +285,8 @@ std::string TextEdit::unparse(const Text
 }
 
 llvm::Optional<DidOpenTextDocumentParams>
-DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
+DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
+                                 JSONOutput &Output) {
   DidOpenTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -285,24 +302,25 @@ DidOpenTextDocumentParams::parse(llvm::y
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentItem::parse(Value);
+      auto Parsed = TextDocumentItem::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "metadata") {
-      auto Parsed = Metadata::parse(Value);
+      auto Parsed = Metadata::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.metadata = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<DidCloseTextDocumentParams>
-DidCloseTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
+DidCloseTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
+                                  JSONOutput &Output) {
   DidCloseTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -317,19 +335,20 @@ DidCloseTextDocumentParams::parse(llvm::
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = TextDocumentIdentifier::parse(Map);
+      auto Parsed = TextDocumentIdentifier::parse(Map, Output);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<DidChangeTextDocumentParams>
-DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
+DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params,
+                                   JSONOutput &Output) {
   DidChangeTextDocumentParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -345,7 +364,7 @@ DidChangeTextDocumentParams::parse(llvm:
       auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
       if (!Map)
         return llvm::None;
-      auto Parsed = TextDocumentIdentifier::parse(Map);
+      auto Parsed = TextDocumentIdentifier::parse(Map, Output);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
@@ -357,20 +376,21 @@ DidChangeTextDocumentParams::parse(llvm:
         auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
         if (!I)
           return llvm::None;
-        auto Parsed = TextDocumentContentChangeEvent::parse(I);
+        auto Parsed = TextDocumentContentChangeEvent::parse(I, Output);
         if (!Parsed)
           return llvm::None;
         Result.contentChanges.push_back(std::move(*Parsed));
       }
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<TextDocumentContentChangeEvent>
-TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params) {
+TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params,
+                                      JSONOutput &Output) {
   TextDocumentContentChangeEvent Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -388,14 +408,14 @@ TextDocumentContentChangeEvent::parse(ll
     if (KeyValue == "text") {
       Result.text = Value->getValue(Storage);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<FormattingOptions>
-FormattingOptions::parse(llvm::yaml::MappingNode *Params) {
+FormattingOptions::parse(llvm::yaml::MappingNode *Params, JSONOutput &Output) {
   FormattingOptions Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -428,7 +448,7 @@ FormattingOptions::parse(llvm::yaml::Map
       }
       Result.insertSpaces = Val;
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
@@ -442,7 +462,8 @@ std::string FormattingOptions::unparse(c
 }
 
 llvm::Optional<DocumentRangeFormattingParams>
-DocumentRangeFormattingParams::parse(llvm::yaml::MappingNode *Params) {
+DocumentRangeFormattingParams::parse(llvm::yaml::MappingNode *Params,
+                                     JSONOutput &Output) {
   DocumentRangeFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -458,29 +479,30 @@ DocumentRangeFormattingParams::parse(llv
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "range") {
-      auto Parsed = Range::parse(Value);
+      auto Parsed = Range::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value);
+      auto Parsed = FormattingOptions::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<DocumentOnTypeFormattingParams>
-DocumentOnTypeFormattingParams::parse(llvm::yaml::MappingNode *Params) {
+DocumentOnTypeFormattingParams::parse(llvm::yaml::MappingNode *Params,
+                                      JSONOutput &Output) {
   DocumentOnTypeFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -505,29 +527,30 @@ DocumentOnTypeFormattingParams::parse(ll
     if (!Value)
       return llvm::None;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "position") {
-      auto Parsed = Position::parse(Value);
+      auto Parsed = Position::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.position = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value);
+      auto Parsed = FormattingOptions::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<DocumentFormattingParams>
-DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params) {
+DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params,
+                                JSONOutput &Output) {
   DocumentFormattingParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -543,23 +566,24 @@ DocumentFormattingParams::parse(llvm::ya
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "options") {
-      auto Parsed = FormattingOptions::parse(Value);
+      auto Parsed = FormattingOptions::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.options = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
-llvm::Optional<Diagnostic> Diagnostic::parse(llvm::yaml::MappingNode *Params) {
+llvm::Optional<Diagnostic> Diagnostic::parse(llvm::yaml::MappingNode *Params,
+                                             JSONOutput &Output) {
   Diagnostic Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -575,7 +599,7 @@ llvm::Optional<Diagnostic> Diagnostic::p
           dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
       if (!Value)
         return llvm::None;
-      auto Parsed = Range::parse(Value);
+      auto Parsed = Range::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
@@ -588,6 +612,10 @@ llvm::Optional<Diagnostic> Diagnostic::p
       if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
         return llvm::None;
       Result.severity = Val;
+    } else if (KeyValue == "code") {
+      // Not currently used
+    } else if (KeyValue == "source") {
+      // Not currently used
     } else if (KeyValue == "message") {
       auto *Value =
           dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
@@ -595,14 +623,14 @@ llvm::Optional<Diagnostic> Diagnostic::p
         return llvm::None;
       Result.message = Value->getValue(Storage);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<CodeActionContext>
-CodeActionContext::parse(llvm::yaml::MappingNode *Params) {
+CodeActionContext::parse(llvm::yaml::MappingNode *Params, JSONOutput &Output) {
   CodeActionContext Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -622,20 +650,20 @@ CodeActionContext::parse(llvm::yaml::Map
         auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
         if (!I)
           return llvm::None;
-        auto Parsed = Diagnostic::parse(I);
+        auto Parsed = Diagnostic::parse(I, Output);
         if (!Parsed)
           return llvm::None;
         Result.diagnostics.push_back(std::move(*Parsed));
       }
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<CodeActionParams>
-CodeActionParams::parse(llvm::yaml::MappingNode *Params) {
+CodeActionParams::parse(llvm::yaml::MappingNode *Params, JSONOutput &Output) {
   CodeActionParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -651,29 +679,30 @@ CodeActionParams::parse(llvm::yaml::Mapp
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "range") {
-      auto Parsed = Range::parse(Value);
+      auto Parsed = Range::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.range = std::move(*Parsed);
     } else if (KeyValue == "context") {
-      auto Parsed = CodeActionContext::parse(Value);
+      auto Parsed = CodeActionContext::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.context = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;
 }
 
 llvm::Optional<TextDocumentPositionParams>
-TextDocumentPositionParams::parse(llvm::yaml::MappingNode *Params) {
+TextDocumentPositionParams::parse(llvm::yaml::MappingNode *Params,
+                                  JSONOutput &Output) {
   TextDocumentPositionParams Result;
   for (auto &NextKeyValue : *Params) {
     auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
@@ -689,17 +718,17 @@ TextDocumentPositionParams::parse(llvm::
 
     llvm::SmallString<10> Storage;
     if (KeyValue == "textDocument") {
-      auto Parsed = TextDocumentIdentifier::parse(Value);
+      auto Parsed = TextDocumentIdentifier::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.textDocument = std::move(*Parsed);
     } else if (KeyValue == "position") {
-      auto Parsed = Position::parse(Value);
+      auto Parsed = Position::parse(Value, Output);
       if (!Parsed)
         return llvm::None;
       Result.position = std::move(*Parsed);
     } else {
-      return llvm::None;
+      logIgnoredField(KeyValue, Output);
     }
   }
   return Result;

Modified: clang-tools-extra/trunk/clangd/Protocol.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=313536&r1=313535&r2=313536&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.h (original)
+++ clang-tools-extra/trunk/clangd/Protocol.h Mon Sep 18 08:02:59 2017
@@ -29,6 +29,8 @@
 namespace clang {
 namespace clangd {
 
+class JSONOutput;
+
 struct URI {
   std::string uri;
   std::string file;
@@ -57,7 +59,7 @@ struct TextDocumentIdentifier {
   URI uri;
 
   static llvm::Optional<TextDocumentIdentifier>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct Position {
@@ -76,7 +78,8 @@ struct Position {
            std::tie(RHS.line, RHS.character);
   }
 
-  static llvm::Optional<Position> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<Position> parse(llvm::yaml::MappingNode *Params,
+                                        JSONOutput &Output);
   static std::string unparse(const Position &P);
 };
 
@@ -94,7 +97,8 @@ struct Range {
     return std::tie(LHS.start, LHS.end) < std::tie(RHS.start, RHS.end);
   }
 
-  static llvm::Optional<Range> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<Range> parse(llvm::yaml::MappingNode *Params,
+                                     JSONOutput &Output);
   static std::string unparse(const Range &P);
 };
 
@@ -121,7 +125,8 @@ struct Location {
 struct Metadata {
   std::vector<std::string> extraFlags;
 
-  static llvm::Optional<Metadata> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<Metadata> parse(llvm::yaml::MappingNode *Params,
+                                        JSONOutput &Output);
 };
 
 struct TextEdit {
@@ -133,7 +138,8 @@ struct TextEdit {
   /// empty string.
   std::string newText;
 
-  static llvm::Optional<TextEdit> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<TextEdit> parse(llvm::yaml::MappingNode *Params,
+                                        JSONOutput &Output);
   static std::string unparse(const TextEdit &P);
 };
 
@@ -150,8 +156,8 @@ struct TextDocumentItem {
   /// The content of the opened text document.
   std::string text;
 
-  static llvm::Optional<TextDocumentItem>
-  parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<TextDocumentItem> parse(llvm::yaml::MappingNode *Params,
+                                                JSONOutput &Output);
 };
 
 struct DidOpenTextDocumentParams {
@@ -162,7 +168,7 @@ struct DidOpenTextDocumentParams {
   llvm::Optional<Metadata> metadata;
 
   static llvm::Optional<DidOpenTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct DidCloseTextDocumentParams {
@@ -170,7 +176,7 @@ struct DidCloseTextDocumentParams {
   TextDocumentIdentifier textDocument;
 
   static llvm::Optional<DidCloseTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct TextDocumentContentChangeEvent {
@@ -178,7 +184,7 @@ struct TextDocumentContentChangeEvent {
   std::string text;
 
   static llvm::Optional<TextDocumentContentChangeEvent>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct DidChangeTextDocumentParams {
@@ -191,7 +197,7 @@ struct DidChangeTextDocumentParams {
   std::vector<TextDocumentContentChangeEvent> contentChanges;
 
   static llvm::Optional<DidChangeTextDocumentParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct FormattingOptions {
@@ -202,7 +208,7 @@ struct FormattingOptions {
   bool insertSpaces;
 
   static llvm::Optional<FormattingOptions>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
   static std::string unparse(const FormattingOptions &P);
 };
 
@@ -217,7 +223,7 @@ struct DocumentRangeFormattingParams {
   FormattingOptions options;
 
   static llvm::Optional<DocumentRangeFormattingParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct DocumentOnTypeFormattingParams {
@@ -234,7 +240,7 @@ struct DocumentOnTypeFormattingParams {
   FormattingOptions options;
 
   static llvm::Optional<DocumentOnTypeFormattingParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct DocumentFormattingParams {
@@ -245,7 +251,7 @@ struct DocumentFormattingParams {
   FormattingOptions options;
 
   static llvm::Optional<DocumentFormattingParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct Diagnostic {
@@ -256,6 +262,15 @@ struct Diagnostic {
   /// client to interpret diagnostics as error, warning, info or hint.
   int severity;
 
+  /// The diagnostic's code. Can be omitted.
+  /// Note: Not currently used by clangd
+  // std::string code;
+
+  /// A human-readable string describing the source of this
+  /// diagnostic, e.g. 'typescript' or 'super lint'.
+  /// Note: Not currently used by clangd
+  // std::string source;
+
   /// The diagnostic's message.
   std::string message;
 
@@ -268,7 +283,8 @@ struct Diagnostic {
            std::tie(RHS.range, RHS.severity, RHS.message);
   }
 
-  static llvm::Optional<Diagnostic> parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<Diagnostic> parse(llvm::yaml::MappingNode *Params,
+                                          JSONOutput &Output);
 };
 
 struct CodeActionContext {
@@ -276,7 +292,7 @@ struct CodeActionContext {
   std::vector<Diagnostic> diagnostics;
 
   static llvm::Optional<CodeActionContext>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 struct CodeActionParams {
@@ -289,8 +305,8 @@ struct CodeActionParams {
   /// Context carrying additional information.
   CodeActionContext context;
 
-  static llvm::Optional<CodeActionParams>
-  parse(llvm::yaml::MappingNode *Params);
+  static llvm::Optional<CodeActionParams> parse(llvm::yaml::MappingNode *Params,
+                                                JSONOutput &Output);
 };
 
 struct TextDocumentPositionParams {
@@ -301,7 +317,7 @@ struct TextDocumentPositionParams {
   Position position;
 
   static llvm::Optional<TextDocumentPositionParams>
-  parse(llvm::yaml::MappingNode *Params);
+  parse(llvm::yaml::MappingNode *Params, JSONOutput &Output);
 };
 
 /// The kind of a completion entry.

Modified: clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp?rev=313536&r1=313535&r2=313536&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp (original)
+++ clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp Mon Sep 18 08:02:59 2017
@@ -45,7 +45,7 @@ struct TextDocumentDidOpenHandler : Hand
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleNotification(llvm::yaml::MappingNode *Params) override {
-    auto DOTDP = DidOpenTextDocumentParams::parse(Params);
+    auto DOTDP = DidOpenTextDocumentParams::parse(Params, Output);
     if (!DOTDP) {
       Output.log("Failed to decode DidOpenTextDocumentParams!\n");
       return;
@@ -62,7 +62,7 @@ struct TextDocumentDidChangeHandler : Ha
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleNotification(llvm::yaml::MappingNode *Params) override {
-    auto DCTDP = DidChangeTextDocumentParams::parse(Params);
+    auto DCTDP = DidChangeTextDocumentParams::parse(Params, Output);
     if (!DCTDP || DCTDP->contentChanges.size() != 1) {
       Output.log("Failed to decode DidChangeTextDocumentParams!\n");
       return;
@@ -80,7 +80,7 @@ struct TextDocumentDidCloseHandler : Han
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleNotification(llvm::yaml::MappingNode *Params) override {
-    auto DCTDP = DidCloseTextDocumentParams::parse(Params);
+    auto DCTDP = DidCloseTextDocumentParams::parse(Params, Output);
     if (!DCTDP) {
       Output.log("Failed to decode DidCloseTextDocumentParams!\n");
       return;
@@ -99,7 +99,7 @@ struct TextDocumentOnTypeFormattingHandl
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto DOTFP = DocumentOnTypeFormattingParams::parse(Params);
+    auto DOTFP = DocumentOnTypeFormattingParams::parse(Params, Output);
     if (!DOTFP) {
       Output.log("Failed to decode DocumentOnTypeFormattingParams!\n");
       return;
@@ -118,7 +118,7 @@ struct TextDocumentRangeFormattingHandle
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto DRFP = DocumentRangeFormattingParams::parse(Params);
+    auto DRFP = DocumentRangeFormattingParams::parse(Params, Output);
     if (!DRFP) {
       Output.log("Failed to decode DocumentRangeFormattingParams!\n");
       return;
@@ -137,7 +137,7 @@ struct TextDocumentFormattingHandler : H
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto DFP = DocumentFormattingParams::parse(Params);
+    auto DFP = DocumentFormattingParams::parse(Params, Output);
     if (!DFP) {
       Output.log("Failed to decode DocumentFormattingParams!\n");
       return;
@@ -155,7 +155,7 @@ struct CodeActionHandler : Handler {
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto CAP = CodeActionParams::parse(Params);
+    auto CAP = CodeActionParams::parse(Params, Output);
     if (!CAP) {
       Output.log("Failed to decode CodeActionParams!\n");
       return;
@@ -173,7 +173,7 @@ struct CompletionHandler : Handler {
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto TDPP = TextDocumentPositionParams::parse(Params);
+    auto TDPP = TextDocumentPositionParams::parse(Params, Output);
     if (!TDPP) {
       Output.log("Failed to decode TextDocumentPositionParams!\n");
       return;
@@ -191,7 +191,7 @@ struct GotoDefinitionHandler : Handler {
       : Handler(Output), Callbacks(Callbacks) {}
 
   void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override {
-    auto TDPP = TextDocumentPositionParams::parse(Params);
+    auto TDPP = TextDocumentPositionParams::parse(Params, Output);
     if (!TDPP) {
       Output.log("Failed to decode TextDocumentPositionParams!\n");
       return;

Modified: clang-tools-extra/trunk/test/clangd/fixits.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/fixits.test?rev=313536&r1=313535&r2=313536&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clangd/fixits.test (original)
+++ clang-tools-extra/trunk/test/clangd/fixits.test Mon Sep 18 08:02:59 2017
@@ -17,6 +17,12 @@ Content-Length: 746
 #
 # CHECK: {"jsonrpc":"2.0","id":2, "result": [{"title":"Apply FixIt 'place parentheses around the assignment to silence this warning'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 32}}, "newText": "("},{"range": {"start": {"line": 0, "character": 37}, "end": {"line": 0, "character": 37}}, "newText": ")"}]]},{"title":"Apply FixIt 'use '==' to turn this assignment into an equality comparison'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 34}, "end": {"line": 0, "character": 35}}, "newText": "=="}]]}]
 #
+Content-Length: 771
+
+{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"file:///foo.c"},"range":{"start":{"line":104,"character":13},"end":{"line":0,"character":35}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":2,"code":"1","source":"foo","message":"using the result of an assignment as a condition without parentheses"},{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":3,"message":"place parentheses around the assignment to silence this warning"},{"range":{"start": {"line": 0, "character": 35}, "end": {"line": 0, "character": 35}},"severity":3,"message":"use '==' to turn this assignment into an equality comparison"}]}}}
+# Make sure unused "code" and "source" fields ignored gracefully
+# CHECK: {"jsonrpc":"2.0","id":2, "result": [{"title":"Apply FixIt 'place parentheses around the assignment to silence this warning'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 32}, "end": {"line": 0, "character": 32}}, "newText": "("},{"range": {"start": {"line": 0, "character": 37}, "end": {"line": 0, "character": 37}}, "newText": ")"}]]},{"title":"Apply FixIt 'use '==' to turn this assignment into an equality comparison'", "command": "clangd.applyFix", "arguments": ["file:///foo.c", [{"range": {"start": {"line": 0, "character": 34}, "end": {"line": 0, "character": 35}}, "newText": "=="}]]}]
+#
 Content-Length: 44
 
 {"jsonrpc":"2.0","id":3,"method":"shutdown"}




More information about the cfe-commits mailing list