LCOV - code coverage report
Current view: top level - clang/tools/extra/clangd - JSONExpr.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 0 100 0.0 %
Date: 2018-07-08 00:08:57 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- JSONExpr.h - JSON expressions, parsing and serialization - C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===---------------------------------------------------------------------===//
       9             : 
      10             : // FIXME: rename to JSON.h now that the scope is wider?
      11             : 
      12             : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
      13             : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
      14             : 
      15             : #include "llvm/ADT/SmallVector.h"
      16             : #include "llvm/ADT/StringRef.h"
      17             : #include "llvm/Support/Error.h"
      18             : #include "llvm/Support/FormatVariadic.h"
      19             : #include "llvm/Support/raw_ostream.h"
      20             : #include <map>
      21             : 
      22             : namespace clang {
      23             : namespace clangd {
      24             : namespace json {
      25             : class Expr;
      26             : template <typename T> Expr toJSON(const llvm::Optional<T> &Opt);
      27             : 
      28             : // An Expr is an JSON value of unknown type.
      29             : // They can be copied, but should generally be moved.
      30             : //
      31             : // === Composing expressions ===
      32             : //
      33             : // You can implicitly construct Exprs from:
      34             : //   - strings: std::string, SmallString, formatv, StringRef, char*
      35             : //              (char*, and StringRef are references, not copies!)
      36             : //   - numbers
      37             : //   - booleans
      38             : //   - null: nullptr
      39             : //   - arrays: {"foo", 42.0, false}
      40             : //   - serializable things: types with toJSON(const T&)->Expr, found by ADL
      41             : //
      42             : // They can also be constructed from object/array helpers:
      43             : //   - json::obj is a type like map<StringExpr, Expr>
      44             : //   - json::ary is a type like vector<Expr>
      45             : // These can be list-initialized, or used to build up collections in a loop.
      46             : // json::ary(Collection) converts all items in a collection to Exprs.
      47             : //
      48             : // === Inspecting expressions ===
      49             : //
      50             : // Each Expr is one of the JSON kinds:
      51             : //   null    (nullptr_t)
      52             : //   boolean (bool)
      53             : //   number  (double)
      54             : //   string  (StringRef)
      55             : //   array   (json::ary)
      56             : //   object  (json::obj)
      57             : //
      58             : // The kind can be queried directly, or implicitly via the typed accessors:
      59             : //   if (Optional<StringRef> S = E.asString()
      60             : //     assert(E.kind() == Expr::String);
      61             : //
      62             : // Array and Object also have typed indexing accessors for easy traversal:
      63             : //   Expected<Expr> E = parse(R"( {"options": {"font": "sans-serif"}} )");
      64             : //   if (json::obj* O = E->asObject())
      65             : //     if (json::obj* Opts = O->getObject("options"))
      66             : //       if (Optional<StringRef> Font = Opts->getString("font"))
      67             : //         assert(Opts->at("font").kind() == Expr::String);
      68             : //
      69             : // === Converting expressions to objects ===
      70             : //
      71             : // The convention is to have a deserializer function findable via ADL:
      72             : //     fromJSON(const json::Expr&, T&)->bool
      73             : // Deserializers are provided for:
      74             : //   - bool
      75             : //   - int
      76             : //   - double
      77             : //   - std::string
      78             : //   - vector<T>, where T is deserializable
      79             : //   - map<string, T>, where T is deserializable
      80             : //   - Optional<T>, where T is deserializable
      81             : //
      82             : // ObjectMapper can help writing fromJSON() functions for object types:
      83             : //   bool fromJSON(const Expr &E, MyStruct &R) {
      84             : //     ObjectMapper O(E);
      85             : //     if (!O || !O.map("mandatory_field", R.MandatoryField))
      86             : //       return false;
      87             : //     O.map("optional_field", R.OptionalField);
      88             : //     return true;
      89             : //   }
      90             : //
      91             : // === Serialization ===
      92             : //
      93             : // Exprs can be serialized to JSON:
      94             : //   1) raw_ostream << Expr                    // Basic formatting.
      95             : //   2) raw_ostream << formatv("{0}", Expr)    // Basic formatting.
      96             : //   3) raw_ostream << formatv("{0:2}", Expr)  // Pretty-print with indent 2.
      97             : //
      98             : // And parsed:
      99             : //   Expected<Expr> E = json::parse("[1, 2, null]");
     100             : //   assert(E && E->kind() == Expr::Array);
     101             : class Expr {
     102             : public:
     103             :   enum Kind {
     104             :     Null,
     105             :     Boolean,
     106             :     Number,
     107             :     String,
     108             :     Array,
     109             :     Object,
     110             :   };
     111             :   class ObjectExpr;
     112             :   class ObjectKey;
     113             :   class ArrayExpr;
     114             : 
     115             :   // It would be nice to have Expr() be null. But that would make {} null too...
     116           0 :   Expr(const Expr &M) { copyFrom(M); }
     117             :   Expr(Expr &&M) { moveFrom(std::move(M)); }
     118             :   // "cheating" move-constructor for moving from initializer_list.
     119           0 :   Expr(const Expr &&M) { moveFrom(std::move(M)); }
     120           0 :   Expr(std::initializer_list<Expr> Elements) : Expr(ArrayExpr(Elements)) {}
     121           0 :   Expr(ArrayExpr &&Elements) : Type(T_Array) {
     122             :     create<ArrayExpr>(std::move(Elements));
     123             :   }
     124           0 :   Expr(ObjectExpr &&Properties) : Type(T_Object) {
     125             :     create<ObjectExpr>(std::move(Properties));
     126             :   }
     127             :   // Strings: types with value semantics.
     128             :   Expr(std::string &&V) : Type(T_String) { create<std::string>(std::move(V)); }
     129           0 :   Expr(const std::string &V) : Type(T_String) { create<std::string>(V); }
     130             :   Expr(const llvm::SmallVectorImpl<char> &V) : Type(T_String) {
     131             :     create<std::string>(V.begin(), V.end());
     132             :   }
     133             :   Expr(const llvm::formatv_object_base &V) : Expr(V.str()){};
     134             :   // Strings: types with reference semantics.
     135           0 :   Expr(llvm::StringRef V) : Type(T_StringRef) { create<llvm::StringRef>(V); }
     136           0 :   Expr(const char *V) : Type(T_StringRef) { create<llvm::StringRef>(V); }
     137           0 :   Expr(std::nullptr_t) : Type(T_Null) {}
     138             :   // Prevent implicit conversions to boolean.
     139             :   template <typename T, typename = typename std::enable_if<
     140             :                             std::is_same<T, bool>::value>::type>
     141           0 :   Expr(T B) : Type(T_Boolean) {
     142             :     create<bool>(B);
     143             :   }
     144             :   // Numbers: arithmetic types that are not boolean.
     145             :   template <
     146             :       typename T,
     147             :       typename = typename std::enable_if<std::is_arithmetic<T>::value>::type,
     148             :       typename = typename std::enable_if<std::integral_constant<
     149             :           bool, !std::is_same<T, bool>::value>::value>::type>
     150           0 :   Expr(T D) : Type(T_Number) {
     151             :     create<double>(D);
     152             :   }
     153             :   // Types with a toJSON(const T&)->Expr function, found by ADL.
     154             :   template <typename T,
     155             :             typename = typename std::enable_if<std::is_same<
     156             :                 Expr, decltype(toJSON(*(const T *)nullptr))>::value>>
     157           0 :   Expr(const T &V) : Expr(toJSON(V)) {}
     158             : 
     159             :   Expr &operator=(const Expr &M) {
     160             :     destroy();
     161             :     copyFrom(M);
     162             :     return *this;
     163             :   }
     164             :   Expr &operator=(Expr &&M) {
     165             :     destroy();
     166             :     moveFrom(std::move(M));
     167             :     return *this;
     168             :   }
     169           0 :   ~Expr() { destroy(); }
     170             : 
     171             :   Kind kind() const {
     172             :     switch (Type) {
     173             :     case T_Null:
     174             :       return Null;
     175             :     case T_Boolean:
     176             :       return Boolean;
     177             :     case T_Number:
     178             :       return Number;
     179             :     case T_String:
     180             :     case T_StringRef:
     181             :       return String;
     182             :     case T_Object:
     183             :       return Object;
     184             :     case T_Array:
     185             :       return Array;
     186             :     }
     187             :     llvm_unreachable("Unknown kind");
     188             :   }
     189             : 
     190             :   // Typed accessors return None/nullptr if the Expr is not of this type.
     191             :   llvm::Optional<std::nullptr_t> asNull() const {
     192           0 :     if (LLVM_LIKELY(Type == T_Null))
     193             :       return nullptr;
     194             :     return llvm::None;
     195             :   }
     196             :   llvm::Optional<bool> asBoolean() const {
     197           0 :     if (LLVM_LIKELY(Type == T_Boolean))
     198             :       return as<bool>();
     199             :     return llvm::None;
     200             :   }
     201             :   llvm::Optional<double> asNumber() const {
     202           0 :     if (LLVM_LIKELY(Type == T_Number))
     203             :       return as<double>();
     204             :     return llvm::None;
     205             :   }
     206           0 :   llvm::Optional<int64_t> asInteger() const {
     207           0 :     if (LLVM_LIKELY(Type == T_Number)) {
     208           0 :       double D = as<double>();
     209           0 :       if (LLVM_LIKELY(std::modf(D, &D) == 0 &&
     210             :                       D >= std::numeric_limits<int64_t>::min() &&
     211           0 :                       D <= std::numeric_limits<int64_t>::max()))
     212           0 :         return D;
     213             :     }
     214             :     return llvm::None;
     215             :   }
     216             :   llvm::Optional<llvm::StringRef> asString() const {
     217           0 :     if (Type == T_String)
     218             :       return llvm::StringRef(as<std::string>());
     219           0 :     if (LLVM_LIKELY(Type == T_StringRef))
     220             :       return as<llvm::StringRef>();
     221             :     return llvm::None;
     222             :   }
     223             :   const ObjectExpr *asObject() const {
     224           0 :     return LLVM_LIKELY(Type == T_Object) ? &as<ObjectExpr>() : nullptr;
     225             :   }
     226             :   ObjectExpr *asObject() {
     227           0 :     return LLVM_LIKELY(Type == T_Object) ? &as<ObjectExpr>() : nullptr;
     228             :   }
     229             :   const ArrayExpr *asArray() const {
     230           0 :     return LLVM_LIKELY(Type == T_Array) ? &as<ArrayExpr>() : nullptr;
     231             :   }
     232             :   ArrayExpr *asArray() {
     233           0 :     return LLVM_LIKELY(Type == T_Array) ? &as<ArrayExpr>() : nullptr;
     234             :   }
     235             : 
     236             :   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Expr &);
     237             : 
     238             : private:
     239             :   void destroy();
     240             :   void copyFrom(const Expr &M);
     241             :   // We allow moving from *const* Exprs, by marking all members as mutable!
     242             :   // This hack is needed to support initializer-list syntax efficiently.
     243             :   // (std::initializer_list<T> is a container of const T).
     244             :   void moveFrom(const Expr &&M);
     245             : 
     246             :   template <typename T, typename... U> void create(U &&... V) {
     247           0 :     new (&as<T>()) T(std::forward<U>(V)...);
     248             :   }
     249             :   template <typename T> T &as() const {
     250           0 :     return *reinterpret_cast<T *>(Union.buffer);
     251             :   }
     252             : 
     253             :   template <typename Indenter>
     254             :   void print(llvm::raw_ostream &, const Indenter &) const;
     255             :   friend struct llvm::format_provider<clang::clangd::json::Expr>;
     256             : 
     257             :   enum ExprType : char {
     258             :     T_Null,
     259             :     T_Boolean,
     260             :     T_Number,
     261             :     T_StringRef,
     262             :     T_String,
     263             :     T_Object,
     264             :     T_Array,
     265             :   };
     266             :   mutable ExprType Type;
     267             : 
     268             : public:
     269             :   // ObjectKey is a used to capture keys in Expr::ObjectExpr. Like Expr but:
     270             :   //   - only strings are allowed
     271             :   //   - it's optimized for the string literal case (Owned == nullptr)
     272             :   class ObjectKey {
     273             :   public:
     274             :     ObjectKey(const char *S) : Data(S) {}
     275           0 :     ObjectKey(llvm::StringRef S) : Data(S) {}
     276             :     ObjectKey(std::string &&V)
     277             :         : Owned(new std::string(std::move(V))), Data(*Owned) {}
     278             :     ObjectKey(const std::string &V) : Owned(new std::string(V)), Data(*Owned) {}
     279             :     ObjectKey(const llvm::SmallVectorImpl<char> &V)
     280             :         : ObjectKey(std::string(V.begin(), V.end())) {}
     281             :     ObjectKey(const llvm::formatv_object_base &V) : ObjectKey(V.str()) {}
     282             : 
     283             :     ObjectKey(const ObjectKey &C) { *this = C; }
     284             :     ObjectKey(ObjectKey &&C) : ObjectKey(static_cast<const ObjectKey &&>(C)) {}
     285             :     ObjectKey &operator=(const ObjectKey &C) {
     286             :       if (C.Owned) {
     287             :         Owned.reset(new std::string(*C.Owned));
     288             :         Data = *Owned;
     289             :       } else {
     290             :         Data = C.Data;
     291             :       }
     292             :       return *this;
     293             :     }
     294             :     ObjectKey &operator=(ObjectKey &&) = default;
     295             : 
     296             :     operator llvm::StringRef() const { return Data; }
     297             : 
     298             :     friend bool operator<(const ObjectKey &L, const ObjectKey &R) {
     299           0 :       return L.Data < R.Data;
     300             :     }
     301             : 
     302             :     // "cheating" move-constructor for moving from initializer_list.
     303           0 :     ObjectKey(const ObjectKey &&V) {
     304             :       Owned = std::move(V.Owned);
     305           0 :       Data = V.Data;
     306             :     }
     307             : 
     308             :   private:
     309             :     mutable std::unique_ptr<std::string> Owned; // mutable for cheating.
     310             :     llvm::StringRef Data;
     311             :   };
     312             : 
     313             :   class ObjectExpr : public std::map<ObjectKey, Expr> {
     314             :   public:
     315           0 :     explicit ObjectExpr() {}
     316             :     // Use a custom struct for list-init, because pair forces extra copies.
     317             :     struct KV;
     318             :     explicit ObjectExpr(std::initializer_list<KV> Properties);
     319             : 
     320             :     // Allow [] as if Expr was default-constructible as null.
     321             :     Expr &operator[](const ObjectKey &K) {
     322             :       return emplace(K, Expr(nullptr)).first->second;
     323             :     }
     324             :     Expr &operator[](ObjectKey &&K) {
     325             :       return emplace(std::move(K), Expr(nullptr)).first->second;
     326             :     }
     327             : 
     328             :     // Look up a property, returning nullptr if it doesn't exist.
     329             :     json::Expr *get(const ObjectKey &K) {
     330             :       auto I = find(K);
     331           0 :       if (I == end())
     332             :         return nullptr;
     333           0 :       return &I->second;
     334             :     }
     335             :     const json::Expr *get(const ObjectKey &K) const {
     336             :       auto I = find(K);
     337           0 :       if (I == end())
     338             :         return nullptr;
     339           0 :       return &I->second;
     340             :     }
     341             :     // Typed accessors return None/nullptr if
     342             :     //   - the property doesn't exist
     343             :     //   - or it has the wrong type
     344           0 :     llvm::Optional<std::nullptr_t> getNull(const ObjectKey &K) const {
     345           0 :       if (auto *V = get(K))
     346           0 :         return V->asNull();
     347             :       return llvm::None;
     348             :     }
     349             :     llvm::Optional<bool> getBoolean(const ObjectKey &K) const {
     350             :       if (auto *V = get(K))
     351             :         return V->asBoolean();
     352             :       return llvm::None;
     353             :     }
     354           0 :     llvm::Optional<double> getNumber(const ObjectKey &K) const {
     355           0 :       if (auto *V = get(K))
     356             :         return V->asNumber();
     357             :       return llvm::None;
     358             :     }
     359           0 :     llvm::Optional<int64_t> getInteger(const ObjectKey &K) const {
     360           0 :       if (auto *V = get(K))
     361           0 :         return V->asInteger();
     362             :       return llvm::None;
     363             :     }
     364           0 :     llvm::Optional<llvm::StringRef> getString(const ObjectKey &K) const {
     365           0 :       if (auto *V = get(K))
     366             :         return V->asString();
     367             :       return llvm::None;
     368             :     }
     369             :     const ObjectExpr *getObject(const ObjectKey &K) const {
     370             :       if (auto *V = get(K))
     371             :         return V->asObject();
     372             :       return nullptr;
     373             :     }
     374           0 :     ObjectExpr *getObject(const ObjectKey &K) {
     375           0 :       if (auto *V = get(K))
     376             :         return V->asObject();
     377             :       return nullptr;
     378             :     }
     379             :     const ArrayExpr *getArray(const ObjectKey &K) const {
     380             :       if (auto *V = get(K))
     381             :         return V->asArray();
     382             :       return nullptr;
     383             :     }
     384           0 :     ArrayExpr *getArray(const ObjectKey &K) {
     385           0 :       if (auto *V = get(K))
     386             :         return V->asArray();
     387             :       return nullptr;
     388             :     }
     389             :   };
     390             : 
     391           0 :   class ArrayExpr : public std::vector<Expr> {
     392             :   public:
     393             :     explicit ArrayExpr() {}
     394           0 :     explicit ArrayExpr(std::initializer_list<Expr> Elements) {
     395           0 :       reserve(Elements.size());
     396           0 :       for (const Expr &V : Elements)
     397           0 :         emplace_back(std::move(V));
     398           0 :     };
     399             :     template <typename Collection> explicit ArrayExpr(const Collection &C) {
     400             :       for (const auto &V : C)
     401             :         emplace_back(V);
     402             :     }
     403             : 
     404             :     // Typed accessors return None/nullptr if the element has the wrong type.
     405             :     llvm::Optional<std::nullptr_t> getNull(size_t I) const {
     406             :       return (*this)[I].asNull();
     407             :     }
     408             :     llvm::Optional<bool> getBoolean(size_t I) const {
     409           0 :       return (*this)[I].asBoolean();
     410             :     }
     411             :     llvm::Optional<double> getNumber(size_t I) const {
     412             :       return (*this)[I].asNumber();
     413             :     }
     414             :     llvm::Optional<int64_t> getInteger(size_t I) const {
     415           0 :       return (*this)[I].asInteger();
     416             :     }
     417             :     llvm::Optional<llvm::StringRef> getString(size_t I) const {
     418             :       return (*this)[I].asString();
     419             :     }
     420             :     const ObjectExpr *getObject(size_t I) const {
     421             :       return (*this)[I].asObject();
     422             :     }
     423             :     ObjectExpr *getObject(size_t I) { return (*this)[I].asObject(); }
     424             :     const ArrayExpr *getArray(size_t I) const { return (*this)[I].asArray(); }
     425           0 :     ArrayExpr *getArray(size_t I) { return (*this)[I].asArray(); }
     426             :   };
     427             : 
     428             : private:
     429             :   mutable llvm::AlignedCharArrayUnion<bool, double, llvm::StringRef,
     430             :                                       std::string, ArrayExpr, ObjectExpr>
     431             :       Union;
     432             : };
     433             : 
     434             : bool operator==(const Expr &, const Expr &);
     435             : inline bool operator!=(const Expr &L, const Expr &R) { return !(L == R); }
     436           0 : inline bool operator==(const Expr::ObjectKey &L, const Expr::ObjectKey &R) {
     437           0 :   return llvm::StringRef(L) == llvm::StringRef(R);
     438             : }
     439             : inline bool operator!=(const Expr::ObjectKey &L, const Expr::ObjectKey &R) {
     440             :   return !(L == R);
     441             : }
     442             : 
     443           0 : struct Expr::ObjectExpr::KV {
     444             :   ObjectKey K;
     445             :   Expr V;
     446             : };
     447             : 
     448           0 : inline Expr::ObjectExpr::ObjectExpr(std::initializer_list<KV> Properties) {
     449           0 :   for (const auto &P : Properties)
     450           0 :     emplace(std::move(P.K), std::move(P.V));
     451           0 : }
     452             : 
     453             : // Give Expr::{Object,Array} more convenient names for literal use.
     454             : using obj = Expr::ObjectExpr;
     455             : using ary = Expr::ArrayExpr;
     456             : 
     457             : // Standard deserializers.
     458           0 : inline bool fromJSON(const json::Expr &E, std::string &Out) {
     459           0 :   if (auto S = E.asString()) {
     460           0 :     Out = *S;
     461             :     return true;
     462             :   }
     463             :   return false;
     464             : }
     465             : inline bool fromJSON(const json::Expr &E, int &Out) {
     466           0 :   if (auto S = E.asInteger()) {
     467           0 :     Out = *S;
     468             :     return true;
     469             :   }
     470             :   return false;
     471             : }
     472             : inline bool fromJSON(const json::Expr &E, double &Out) {
     473             :   if (auto S = E.asNumber()) {
     474             :     Out = *S;
     475             :     return true;
     476             :   }
     477             :   return false;
     478             : }
     479             : inline bool fromJSON(const json::Expr &E, bool &Out) {
     480           0 :   if (auto S = E.asBoolean()) {
     481           0 :     Out = *S;
     482             :     return true;
     483             :   }
     484             :   return false;
     485             : }
     486             : template <typename T>
     487           0 : bool fromJSON(const json::Expr &E, llvm::Optional<T> &Out) {
     488           0 :   if (E.asNull()) {
     489             :     Out = llvm::None;
     490           0 :     return true;
     491             :   }
     492             :   T Result;
     493           0 :   if (!fromJSON(E, Result))
     494             :     return false;
     495             :   Out = std::move(Result);
     496             :   return true;
     497             : }
     498           0 : template <typename T> bool fromJSON(const json::Expr &E, std::vector<T> &Out) {
     499             :   if (auto *A = E.asArray()) {
     500           0 :     Out.clear();
     501           0 :     Out.resize(A->size());
     502           0 :     for (size_t I = 0; I < A->size(); ++I)
     503           0 :       if (!fromJSON((*A)[I], Out[I]))
     504             :         return false;
     505             :     return true;
     506             :   }
     507             :   return false;
     508             : }
     509             : template <typename T>
     510           0 : bool fromJSON(const json::Expr &E, std::map<std::string, T> &Out) {
     511             :   if (auto *O = E.asObject()) {
     512             :     Out.clear();
     513           0 :     for (const auto &KV : *O)
     514           0 :       if (!fromJSON(KV.second, Out[llvm::StringRef(KV.first)]))
     515             :         return false;
     516             :     return true;
     517             :   }
     518             :   return false;
     519             : }
     520             : 
     521             : template <typename T>
     522             : json::Expr toJSON(const llvm::Optional<T>& Opt) {
     523             :   return Opt ? json::Expr(*Opt) : json::Expr(nullptr);
     524             : }
     525             : 
     526             : // Helper for mapping JSON objects onto protocol structs.
     527             : // See file header for example.
     528             : class ObjectMapper {
     529             : public:
     530           0 :   ObjectMapper(const json::Expr &E) : O(E.asObject()) {}
     531             : 
     532             :   // True if the expression is an object.
     533             :   // Must be checked before calling map().
     534             :   operator bool() { return O; }
     535             : 
     536             :   // Maps a property to a field, if it exists.
     537           0 :   template <typename T> bool map(const char *Prop, T &Out) {
     538             :     assert(*this && "Must check this is an object before calling map()");
     539           0 :     if (const json::Expr *E = O->get(Prop))
     540           0 :       return fromJSON(*E, Out);
     541             :     return false;
     542             :   }
     543             : 
     544             :   // Optional requires special handling, because missing keys are OK.
     545           0 :   template <typename T> bool map(const char *Prop, llvm::Optional<T> &Out) {
     546             :     assert(*this && "Must check this is an object before calling map()");
     547           0 :     if (const json::Expr *E = O->get(Prop))
     548           0 :       return fromJSON(*E, Out);
     549             :     Out = llvm::None;
     550           0 :     return true;
     551             :   }
     552             : 
     553             : private:
     554             :   const json::obj *O;
     555             : };
     556             : 
     557             : llvm::Expected<Expr> parse(llvm::StringRef JSON);
     558             : 
     559           0 : class ParseError : public llvm::ErrorInfo<ParseError> {
     560             :   const char *Msg;
     561             :   unsigned Line, Column, Offset;
     562             : 
     563             : public:
     564             :   static char ID;
     565             :   ParseError(const char *Msg, unsigned Line, unsigned Column, unsigned Offset)
     566             :       : Msg(Msg), Line(Line), Column(Column), Offset(Offset) {}
     567           0 :   void log(llvm::raw_ostream &OS) const override {
     568           0 :     OS << llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line, Column, Offset, Msg);
     569           0 :   }
     570             :   std::error_code convertToErrorCode() const override {
     571             :     return llvm::inconvertibleErrorCode();
     572             :   }
     573             : };
     574             : 
     575             : } // namespace json
     576             : } // namespace clangd
     577             : } // namespace clang
     578             : 
     579             : namespace llvm {
     580             : template <> struct format_provider<clang::clangd::json::Expr> {
     581             :   static void format(const clang::clangd::json::Expr &, raw_ostream &,
     582             :                      StringRef);
     583             : };
     584             : } // namespace llvm
     585             : 
     586             : #endif

Generated by: LCOV version 1.13